|
| 1 | +# Platform detection |
| 2 | +ifeq ($(OS),Windows_NT) |
| 3 | +PLATFORM := windows |
| 4 | +else |
| 5 | +SHELL := /bin/zsh |
| 6 | +PLATFORM := macos |
| 7 | +endif |
| 8 | + |
| 9 | +BUILD_DIR := build |
| 10 | +OBJ_DIR := $(BUILD_DIR)/obj |
| 11 | +BIN_DIR := $(BUILD_DIR)/bin |
| 12 | + |
| 13 | +# ---------- NTSC library sources (platform-independent) -------------------- |
| 14 | +NTSC_CPP := \ |
| 15 | + src/common/ntsc_signal.cpp \ |
| 16 | + src/common/ntsc_params.cpp \ |
| 17 | + src/common/ntsc_effects.cpp \ |
| 18 | + src/common/ntsc_encoder.cpp \ |
| 19 | + src/common/ntsc_decoder.cpp \ |
| 20 | + src/common/ntsc_processor.cpp |
| 21 | + |
| 22 | +NTSC_OBJS := $(NTSC_CPP:src/%.cpp=$(OBJ_DIR)/%.o) |
| 23 | + |
| 24 | +# ---------- Plugin sources (shared across platforms) ----------------------- |
| 25 | +PLUGIN_SRC := src/plugin/rf2_ntsc.cpp |
| 26 | +PLUGIN_OBJ := $(OBJ_DIR)/plugin/rf2_ntsc.o |
| 27 | +PLUGIN_R := src/plugin/rf2_ntsc.r |
| 28 | + |
| 29 | +# ========================================================================== |
| 30 | +ifeq ($(PLATFORM),windows) |
| 31 | +# ===== Windows (MinGW-w64) — plugin only ================================== |
| 32 | + |
| 33 | +CXX := g++ |
| 34 | +CXXFLAGS := -std=c++20 -O3 -march=x86-64-v2 -ffast-math -flto \ |
| 35 | + -Wall -Wextra -Wpedantic -Iinclude |
| 36 | +LDFLAGS := -flto -static-libgcc -static-libstdc++ |
| 37 | + |
| 38 | +AE_SDK_DIR := 3rdparty/windows/AfterEffectsSDK_25.6_61_win/ae25.6_61.64bit.AfterEffectsSDK |
| 39 | +PR_SDK_DIR := 3rdparty/windows/Premiere Pro 26.0 C++ SDK |
| 40 | +PIPL_TOOL := $(AE_SDK_DIR)/Examples/Resources/PiPLtool.exe |
| 41 | + |
| 42 | +SDK_INCLUDES := \ |
| 43 | + -I"$(AE_SDK_DIR)/Examples/Headers" \ |
| 44 | + -I"$(AE_SDK_DIR)/Examples/Headers/SP" \ |
| 45 | + -I"$(AE_SDK_DIR)/Examples/Util" \ |
| 46 | + -I"$(PR_SDK_DIR)/Examples/Headers" |
| 47 | + |
| 48 | +# MinGW compatibility: _WINDOWS triggers platform detection in the Adobe SDK |
| 49 | +# headers (SPConfig.h sets WIN_ENV, which enables Windows type definitions). |
| 50 | +# __int64 is an MSVC keyword that g++ doesn't recognize in strict C++ mode. |
| 51 | +SDK_COMPAT := -D_WINDOWS -DMSWindows -D"__int64=long long" -Wno-unknown-pragmas |
| 52 | + |
| 53 | +# PiPL resource pipeline intermediates |
| 54 | +PIPL_RR := $(OBJ_DIR)/plugin/rf2_ntsc.rr |
| 55 | +PIPL_RRC := $(OBJ_DIR)/plugin/rf2_ntsc.rrc |
| 56 | +PIPL_RC := $(OBJ_DIR)/plugin/rf2_ntsc_pipl.rc |
| 57 | +PIPL_RES := $(OBJ_DIR)/plugin/rf2_ntsc_pipl.o |
| 58 | + |
| 59 | +PLUGIN_DLL := $(BUILD_DIR)/plugin/Analog_NTSC.prm |
| 60 | +PLUGIN_INSTALLER := $(BUILD_DIR)/Analog-NTSC-Setup.exe |
| 61 | + |
| 62 | +.PHONY: plugin plugin-release clean |
| 63 | + |
| 64 | +plugin: $(PLUGIN_DLL) |
| 65 | + |
| 66 | +# Self-extracting installer (requires NSIS: pacman -S mingw-w64-x86_64-nsis) |
| 67 | +plugin-release: $(PLUGIN_INSTALLER) |
| 68 | + |
| 69 | +$(PLUGIN_DLL): $(NTSC_OBJS) $(PLUGIN_OBJ) $(PIPL_RES) |
| 70 | + @mkdir -p "$(@D)" |
| 71 | + $(CXX) -shared -o "$@" $^ $(LDFLAGS) |
| 72 | + |
| 73 | +$(PLUGIN_INSTALLER): $(PLUGIN_DLL) |
| 74 | + makensis src/plugin/installer.nsi |
| 75 | + |
| 76 | +# PiPL resource pipeline: .r -> preprocess -> PiPLTool -> preprocess -> windres |
| 77 | +$(PIPL_RR): $(PLUGIN_R) |
| 78 | + @mkdir -p $(@D) |
| 79 | + $(CXX) -E -P -w -x c $(SDK_INCLUDES) $(SDK_COMPAT) \ |
| 80 | + -I"$(AE_SDK_DIR)/Examples/Resources" \ |
| 81 | + $< > $@ |
| 82 | + |
| 83 | +$(PIPL_RRC): $(PIPL_RR) |
| 84 | + "$(PIPL_TOOL)" $< $@ |
| 85 | + |
| 86 | +# PiPLtool emits MSVC rc.exe syntax; fix three issues for GNU windres: |
| 87 | +# 1. Remove DISCARDABLE (unsupported for custom resource types) |
| 88 | +# 2. Strip L suffix from integer literals (0x65564552L -> 0x65564552) |
| 89 | +# 3. Add missing commas between data values |
| 90 | +$(PIPL_RC): $(PIPL_RRC) |
| 91 | + $(CXX) -E -P -DMSWindows -w -x c $< | \ |
| 92 | + sed -e 's/DISCARDABLE//' \ |
| 93 | + -e 's/\([0-9a-fA-F]\)L\([, ]\)/\1\2/g' \ |
| 94 | + -e 's/\([0-9a-fA-F]\)L$$/\1/' \ |
| 95 | + -e '/^ /{ /,[[:space:]]*$$/!s/$$/,/; }' \ |
| 96 | + > $@ |
| 97 | + |
| 98 | +$(PIPL_RES): $(PIPL_RC) |
| 99 | + windres $< -o $@ |
| 100 | + |
| 101 | +# Plugin source (with SDK includes) |
| 102 | +$(PLUGIN_OBJ): $(PLUGIN_SRC) |
| 103 | + @mkdir -p $(@D) |
| 104 | + $(CXX) $(CXXFLAGS) $(SDK_INCLUDES) $(SDK_COMPAT) \ |
| 105 | + -fvisibility=hidden -Wno-multichar \ |
| 106 | + -Wno-unused-parameter -Wno-missing-field-initializers \ |
| 107 | + -c $< -o $@ |
| 108 | + |
| 109 | +# NTSC library objects (explicit subdirectory rule for Windows Make compatibility) |
| 110 | +$(OBJ_DIR)/common/%.o: src/common/%.cpp |
| 111 | + @mkdir -p $(dir $@) |
| 112 | + $(CXX) $(CXXFLAGS) -c $< -o $@ |
| 113 | + |
| 114 | +else |
| 115 | +# ===== macOS (clang++) ===================================================== |
| 116 | + |
| 117 | +CXX := clang++ |
| 118 | +OBJCXX := clang++ |
| 119 | + |
| 120 | +CXXFLAGS := -std=c++20 -O3 -march=native -ffast-math -flto -Wall -Wextra -Wpedantic -Iinclude |
| 121 | +OBJCXXFLAGS := $(CXXFLAGS) -fobjc-arc |
| 122 | +LDFLAGS := -lcompression -flto |
| 123 | + |
| 124 | +FRAMEWORKS_APP := \ |
| 125 | + -framework Cocoa \ |
| 126 | + -framework Metal \ |
| 127 | + -framework MetalKit \ |
| 128 | + -framework AVFoundation \ |
| 129 | + -framework AudioToolbox \ |
| 130 | + -framework CoreAudio \ |
| 131 | + -framework QuartzCore |
| 132 | + |
| 133 | +# macOS COMMON includes ntrf_container (uses Apple compression library) |
| 134 | +COMMON_CPP := src/common/ntrf_container.cpp $(NTSC_CPP) |
| 135 | +COMMON_OBJS := $(COMMON_CPP:src/%.cpp=$(OBJ_DIR)/%.o) |
| 136 | + |
| 137 | +ENCODER_CPP := src/encoder/main.cpp |
| 138 | +ENCODER_OBJS := $(ENCODER_CPP:src/%.cpp=$(OBJ_DIR)/%.o) |
| 139 | + |
| 140 | +APP_MM := src/app/main.mm |
| 141 | +APP_OBJS := $(APP_MM:src/%.mm=$(OBJ_DIR)/%.o) |
| 142 | + |
| 143 | +ENCODER_BIN := $(BIN_DIR)/ntsc-encode |
| 144 | +PLAYER_BIN := $(BIN_DIR)/ntsc-player |
| 145 | + |
| 146 | +NDI_SDK_DIR := ndisdk |
| 147 | +NDI_APP_CPPFLAGS := |
| 148 | +NDI_APP_LDFLAGS := |
| 149 | +ifneq ($(wildcard $(NDI_SDK_DIR)/include/Processing.NDI.Lib.h),) |
| 150 | +NDI_APP_CPPFLAGS += -DHAVE_NDI_SDK=1 -I$(NDI_SDK_DIR)/include |
| 151 | +NDI_APP_LDFLAGS += -L$(NDI_SDK_DIR)/lib/macOS -lndi -Wl,-rpath,@executable_path/../../ndisdk/lib/macOS |
| 152 | +endif |
| 153 | + |
| 154 | +# ---------- Adobe plugin SDK paths (macOS) --------------------------------- |
| 155 | +AE_SDK_DIR := 3rdparty/macos/AfterEffectsSDK_25.6_61_mac/ae25.6_61.64bit.AfterEffectsSDK |
| 156 | +PR_SDK_DIR := 3rdparty/macos/Premiere Pro 26.0 C++ SDK |
| 157 | + |
| 158 | +PLUGIN_STAMP := $(BUILD_DIR)/plugin/.stamp |
| 159 | + |
| 160 | +# ---------- targets -------------------------------------------------------- |
| 161 | +.PHONY: all clean run-player plugin plugin-release |
| 162 | + |
| 163 | +all: $(ENCODER_BIN) $(PLAYER_BIN) |
| 164 | + |
| 165 | +$(ENCODER_BIN): $(COMMON_OBJS) $(ENCODER_OBJS) | $(BIN_DIR) |
| 166 | + $(CXX) $(CXXFLAGS) $^ -o $@ $(LDFLAGS) |
| 167 | + |
| 168 | +$(PLAYER_BIN): $(COMMON_OBJS) $(APP_OBJS) | $(BIN_DIR) |
| 169 | + $(OBJCXX) $(OBJCXXFLAGS) $(NDI_APP_CPPFLAGS) $^ -o $@ $(LDFLAGS) $(NDI_APP_LDFLAGS) $(FRAMEWORKS_APP) |
| 170 | + |
| 171 | +$(OBJ_DIR)/%.o: src/%.cpp |
| 172 | + @mkdir -p $(dir $@) |
| 173 | + $(CXX) $(CXXFLAGS) -c $< -o $@ |
| 174 | + |
| 175 | +$(OBJ_DIR)/%.o: src/%.mm |
| 176 | + @mkdir -p $(dir $@) |
| 177 | + $(OBJCXX) $(OBJCXXFLAGS) $(NDI_APP_CPPFLAGS) -c $< -o $@ |
| 178 | + |
| 179 | +$(BIN_DIR): |
| 180 | + @mkdir -p $(BIN_DIR) |
| 181 | + |
| 182 | +run-player: $(PLAYER_BIN) |
| 183 | + $(PLAYER_BIN) |
| 184 | + |
| 185 | +# ---------- Premiere Pro plugin (macOS) ------------------------------------ |
| 186 | +plugin: $(PLUGIN_STAMP) |
| 187 | + |
| 188 | +$(PLUGIN_OBJ): $(PLUGIN_SRC) |
| 189 | + @mkdir -p $(@D) |
| 190 | + $(CXX) $(CXXFLAGS) \ |
| 191 | + -I'$(AE_SDK_DIR)/Examples/Headers' \ |
| 192 | + -I'$(AE_SDK_DIR)/Examples/Headers/SP' \ |
| 193 | + -I'$(AE_SDK_DIR)/Examples/Util' \ |
| 194 | + -I'$(PR_SDK_DIR)/Examples/Headers' \ |
| 195 | + -fvisibility=hidden -Wno-four-char-constants \ |
| 196 | + -Wno-unused-parameter -Wno-missing-field-initializers \ |
| 197 | + -c $< -o $@ |
| 198 | + |
| 199 | +$(PLUGIN_STAMP): $(COMMON_OBJS) $(PLUGIN_OBJ) $(PLUGIN_R) src/plugin/Info.plist |
| 200 | + @mkdir -p '$(BUILD_DIR)/plugin/Analog NTSC.plugin/Contents/MacOS' |
| 201 | + @mkdir -p '$(BUILD_DIR)/plugin/Analog NTSC.plugin/Contents/Resources' |
| 202 | + $(CXX) -dynamiclib -o '$(BUILD_DIR)/plugin/Analog NTSC.plugin/Contents/MacOS/Analog NTSC' \ |
| 203 | + $(COMMON_OBJS) $(PLUGIN_OBJ) $(LDFLAGS) |
| 204 | + xcrun Rez -d AE_OS_MAC \ |
| 205 | + -I '$(AE_SDK_DIR)/Examples/Headers' \ |
| 206 | + -I '$(AE_SDK_DIR)/Examples/Resources' \ |
| 207 | + -I '$(PR_SDK_DIR)/Examples/Headers' \ |
| 208 | + $(PLUGIN_R) -o '$(BUILD_DIR)/plugin/Analog NTSC.plugin/Contents/Resources/Analog NTSC.rsrc' |
| 209 | + cp src/plugin/Info.plist '$(BUILD_DIR)/plugin/Analog NTSC.plugin/Contents/Info.plist' |
| 210 | + @touch $@ |
| 211 | + |
| 212 | +# ---------- Plugin installer DMG ------------------------------------------- |
| 213 | +PLUGIN_PKG := $(BUILD_DIR)/Install Analog NTSC.pkg |
| 214 | +PLUGIN_DMG := $(BUILD_DIR)/Analog-NTSC.dmg |
| 215 | +PLUGIN_INSTALL_DIR := /Library/Application Support/Adobe/Common/Plug-ins/7.0/MediaCore |
| 216 | + |
| 217 | +plugin-release: $(PLUGIN_DMG) |
| 218 | + |
| 219 | +$(PLUGIN_DMG): $(PLUGIN_STAMP) |
| 220 | + @rm -rf '$(BUILD_DIR)/pkg-root' '$(BUILD_DIR)/dmg-stage' |
| 221 | + @mkdir -p '$(BUILD_DIR)/pkg-root' |
| 222 | + @cp -R '$(BUILD_DIR)/plugin/Analog NTSC.plugin' '$(BUILD_DIR)/pkg-root/' |
| 223 | + pkgbuild --root '$(BUILD_DIR)/pkg-root' \ |
| 224 | + --identifier day.kevin.analog-ntsc \ |
| 225 | + --version 1.0 \ |
| 226 | + --install-location '$(PLUGIN_INSTALL_DIR)' \ |
| 227 | + '$(PLUGIN_PKG)' |
| 228 | + @mkdir -p '$(BUILD_DIR)/dmg-stage' |
| 229 | + @mv '$(PLUGIN_PKG)' '$(BUILD_DIR)/dmg-stage/' |
| 230 | + hdiutil create -volname 'Analog NTSC' \ |
| 231 | + -srcfolder '$(BUILD_DIR)/dmg-stage' \ |
| 232 | + -ov -format UDZO \ |
| 233 | + '$(PLUGIN_DMG)' |
| 234 | + @rm -rf '$(BUILD_DIR)/pkg-root' '$(BUILD_DIR)/dmg-stage' |
| 235 | + @echo '=> $(PLUGIN_DMG)' |
| 236 | + |
| 237 | +endif |
| 238 | +# ========================================================================== |
| 239 | + |
| 240 | +clean: |
| 241 | + rm -rf $(BUILD_DIR) |
0 commit comments