使用AI的能力编译ARM版本RDM

前言

笔者使用M芯片的mac电脑,在27寸的4k显示器,使用2048的缩放,可以开启hidpi,且显示大小合适,观感舒适,当然使用5k显示器效果最佳。毕竟mac自己出了5k的imac pro。笔者使用开源项目rdm:RDM,但是RDM的作者已经不维护了。目前分发版本只有x86的Intel版本,想着反正是C++代码,是不是自己在M芯片的电脑上编译一下就行了,来试试,开干。

准备

下载RDM源码:https://github.com/avibrazil/RDM

可以看到这个项目还是很火的,基本上大部分是C++写的

重点关注makefile和license

这个是无任何协议说明的,根据这段说明,可以使用,看看Makefile

这个要改,使用man uname看看

试试,为arm64

先改一下

笔者虽然懂C++,但是没有任何系统桌面软件开发经验,先make试试效果

使用AI

首次make,跳坑,说识别不了display这个定义

bash 复制代码
./utils.h:26:51: error: use of undeclared identifier 'display'; did you mean 'eDisplay'?
   26 |         void CGSGetCurrentDisplayMode(CGDirectDisplayID display, int* modeNum);
      |                                                         ^~~~~~~
      |                                                         eDisplay
/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/System/Library/Frameworks/CoreServices.framework/Frameworks/AE.framework/Headers/AERegistry.h:949:3: note: 'eDisplay' declared here
  949 |   eDisplay                      = 'edds',
      |   ^
In file included from cmdline.mm:5:
./utils.h:26:8: error: variable has incomplete type 'void'
   26 |         void CGSGetCurrentDisplayMode(CGDirectDisplayID display, int* modeNum);
      |              ^
./utils.h:26:33: error: use of undeclared identifier 'CGDirectDisplayID'
   26 |         void CGSGetCurrentDisplayMode(CGDirectDisplayID display, int* modeNum);
      |                                       ^
./utils.h:26:63: error: expected '(' for function-style cast or type construction
   26 |         void CGSGetCurrentDisplayMode(CGDirectDisplayID display, int* modeNum);
      |                                                                  ~~~^
./utils.h:26:65: error: use of undeclared identifier 'modeNum'
   26 |         void CGSGetCurrentDisplayMode(CGDirectDisplayID display, int* modeNum);
      |                                                                       ^
./utils.h:27:76: error: use of undeclared identifier 'display'; did you mean 'eDisplay'?
   27 |         void CGSConfigureDisplayMode(CGDisplayConfigRef config, CGDirectDisplayID display, int modeNum);
      |                                                                                   ^~~~~~~
      |                                                                                   eDisplay
/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/System/Library/Frameworks/CoreServices.framework/Frameworks/AE.framework/Headers/AERegistry.h:949:3: note: 'eDisplay' declared here
  949 |   eDisplay                      = 'edds',
      |   ^
In file included from cmdline.mm:5:
./utils.h:27:7: error: variable has incomplete type 'void'
   27 |         void CGSConfigureDisplayMode(CGDisplayConfigRef config, CGDirectDisplayID display, int modeNum);
      |              ^
./utils.h:27:31: error: use of undeclared identifier 'CGDisplayConfigRef'
   27 |         void CGSConfigureDisplayMode(CGDisplayConfigRef config, CGDirectDisplayID display, int modeNum);
      |                                      ^
./utils.h:27:58: error: use of undeclared identifier 'CGDirectDisplayID'
   27 |         void CGSConfigureDisplayMode(CGDisplayConfigRef config, CGDirectDisplayID display, int modeNum);
      |                                                                 ^
./utils.h:27:89: error: expected '(' for function-style cast or type construction
   27 |         void CGSConfigureDisplayMode(CGDisplayConfigRef config, CGDirectDisplayID display, int modeNum);
      |                                                                                            ~~~ ^
./utils.h:28:52: error: use of undeclared identifier 'display'; did you mean 'eDisplay'?
   28 |         void CGSGetNumberOfDisplayModes(CGDirectDisplayID display, int* nModes);
      |                                                           ^~~~~~~
      |                                                           eDisplay
/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/System/Library/Frameworks/CoreServices.framework/Frameworks/AE.framework/Headers/AERegistry.h:949:3: note: 'eDisplay' declared here
  949 |   eDisplay                      = 'edds',
      |   ^
In file included from cmdline.mm:5:
./utils.h:28:7: error: variable has incomplete type 'void'
   28 |         void CGSGetNumberOfDisplayModes(CGDirectDisplayID display, int* nModes);
      |              ^
./utils.h:28:34: error: use of undeclared identifier 'CGDirectDisplayID'
   28 |         void CGSGetNumberOfDisplayModes(CGDirectDisplayID display, int* nModes);
      |                                         ^
./utils.h:28:64: error: expected '(' for function-style cast or type construction
   28 |         void CGSGetNumberOfDisplayModes(CGDirectDisplayID display, int* nModes);
      |                                                                    ~~~^
./utils.h:28:66: error: use of undeclared identifier 'nModes'; did you mean 'eModem'?
   28 |         void CGSGetNumberOfDisplayModes(CGDirectDisplayID display, int* nModes);
      |                                                                         ^~~~~~
      |                                                                         eModem
/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/System/Library/Frameworks/CoreServices.framework/Frameworks/AE.framework/Headers/AERegistry.h:967:3: note: 'eModem' declared here
  967 |   eModem                        = 'edmm',
      |   ^
In file included from cmdline.mm:5:
./utils.h:29:62: error: use of undeclared identifier 'display'; did you mean 'eDisplay'?
   29 |         void CGSGetDisplayModeDescriptionOfLength(CGDirectDisplayID display, int idx, modes_D4* mode, int length);
      |                                                                     ^~~~~~~
      |                                                                     eDisplay
/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/System/Library/Frameworks/CoreServices.framework/Frameworks/AE.framework/Headers/AERegistry.h:949:3: note: 'eDisplay' declared here
  949 |   eDisplay                      = 'edds',

根据GLM AI诊断:这个是由于.h文件的定义缺失引用,另外定义的变量名称不一致,因为继承的C,AI还说这个是macOS display的私有API啥的

那么我们在utils.h加入引用,修改变量名

cpp 复制代码
#ifndef UTILS_H
#define UTILS_H

#include <CoreGraphics/CGDirectDisplay.h>
#include <CoreGraphics/CoreGraphics.h>
#include <CoreGraphics/CGDisplayConfiguration.h>


typedef union
{
	uint8_t rawData[0xDC];
	struct 
	{
		uint32_t mode;
		uint32_t flags;		// 0x4
		uint32_t width;		// 0x8
		uint32_t height;	// 0xC
		uint32_t depth;		// 0x10
		uint32_t dc2[42];
		uint16_t dc3;
		uint16_t freq;		// 0xBC
		uint32_t dc4[4];
		float density;		// 0xD0
		// freq = 0xBC
		// density = 0xD0
	//	uint32_t freq;
	} derived;
} modes_D4;

extern "C"
{
 	void CGSGetCurrentDisplayMode(CGDirectDisplayID displayID, int* modeNum);
	void CGSConfigureDisplayMode(CGDisplayConfigRef config, CGDirectDisplayID displayID, int modeNum);
	void CGSGetNumberOfDisplayModes(CGDirectDisplayID displayID, int* nModes);
	void CGSGetDisplayModeDescriptionOfLength(CGDirectDisplayID displayID, int idx, modes_D4* mode, int length);
};


void CopyAllDisplayModes(CGDirectDisplayID displayID, modes_D4** modes, int* cnt);
void SetDisplayModeNum(CGDirectDisplayID displayID, int modeNum);

#endif

这里的#if 和#endif,是AI说防止定义冲突啥的,建议使用运行时代码选择编译,说的有道理就加上了

然后执行make clean清理刚刚的编译

再执行make,成功,双击试试效果

效果如下:可以使用,原生ARM应用

遗留问题

遗留问题:

bash 复制代码
SRApplicationDelegate.mm:77:22: warning: 'NSOnState' is deprecated: first deprecated in macOS 10.14 [-Wdeprecated-declarations]
   77 |                                         [item setState: NSOnState];
      |                                                         ^~~~~~~~~
      |                                                         NSControlStateValueOn
/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/System/Library/Frameworks/AppKit.framework/Headers/NSCell.h:355:34: note: 'NSOnState' has been explicitly marked deprecated here
  355 | static const NSControlStateValue NSOnState API_DEPRECATED_WITH_REPLACEMENT("NSControlStateValueOn", macos(10.0,10.14)) = NSControlStateValueOn;
      |                                  ^
SRApplicationDelegate.mm:161:22: warning: 'NSOnState' is deprecated: first deprecated in macOS 10.14 [-Wdeprecated-declarations]
  161 |                                         [item setState: NSOnState];
      |                                                         ^~~~~~~~~
      |                                                         NSControlStateValueOn
/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/System/Library/Frameworks/AppKit.framework/Headers/NSCell.h:355:34: note: 'NSOnState' has been explicitly marked deprecated here
  355 | static const NSControlStateValue NSOnState API_DEPRECATED_WITH_REPLACEMENT("NSControlStateValueOn", macos(10.0,10.14)) = NSControlStateValueOn;
      |                                  ^
SRApplicationDelegate.mm:247:14: warning: 'setImage:' is deprecated: first deprecated in macOS 10.14 - Use the receiver's button.image instead [-Wdeprecated-declarations]
  247 |         [statusItem setImage: statusImage];
      |                     ^
/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/System/Library/Frameworks/AppKit.framework/Headers/NSStatusItem.h:75:39: note: property 'image' is declared deprecated here
   75 | @property (nullable, strong) NSImage *image API_DEPRECATED("Use the receiver's button.image instead", macos(10.0,10.14));
      |                                       ^
/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/System/Library/Frameworks/AppKit.framework/Headers/NSStatusItem.h:75:39: note: 'setImage:' has been explicitly marked deprecated here
SRApplicationDelegate.mm:248:14: warning: 'setHighlightMode:' is deprecated: first deprecated in macOS 10.14 - Use the receiver's button.cell.highlightsBy instead [-Wdeprecated-declarations]
  248 |         [statusItem setHighlightMode: YES];
      |                     ^
/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/System/Library/Frameworks/AppKit.framework/Headers/NSStatusItem.h:78:16: note: property 'highlightMode' is declared deprecated here
   78 | @property BOOL highlightMode API_DEPRECATED("Use the receiver's button.cell.highlightsBy instead", macos(10.0,10.14));
      |                ^
/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/System/Library/Frameworks/AppKit.framework/Headers/NSStatusItem.h:78:16: note: 'setHighlightMode:' has been explicitly marked deprecated here
SRApplicationDelegate.mm:252:18: warning: 'image' is deprecated: first deprecated in macOS 10.14 - Use the receiver's button.image instead [-Wdeprecated-declarations]
  252 |     [[statusItem image] setTemplate:YES];
      |                  ^
/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/System/Library/Frameworks/AppKit.framework/Headers/NSStatusItem.h:75:39: note: property 'image' is declared deprecated here
   75 | @property (nullable, strong) NSImage *image API_DEPRECATED("Use the receiver's button.image instead", macos(10.0,10.14));
      |                                       ^
/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/System/Library/Frameworks/AppKit.framework/Headers/NSStatusItem.h:75:39: note: 'image' has been explicitly marked deprecated here
5 warnings generated.

有些废弃类,笔者可以自己修改一下,比如可以完全替代的NSOnState使用NSControlStateValueOn,这个比较好改,而且完全兼容,直接替换即可。其他让AI来修改,代码如下:SRApplicationDelegate.mm

objectivec 复制代码
#import <Foundation/Foundation.h>
#import <AppKit/AppKit.h>

#import "SRApplicationDelegate.h"

#import "utils.h"
#import "ResMenuItem.h"






@implementation SRApplicationDelegate

- (void) showAbout
{
  [NSApp activateIgnoringOtherApps:YES];
  [NSApp orderFrontStandardAboutPanel:self];
}


- (void) quit
{
	[NSApp terminate: self];
}



- (void) refreshStatusMenu
{
	if(statusMenu)
		[statusMenu release];
	
	statusMenu = [[NSMenu alloc] initWithTitle: @""];
	
	uint32_t nDisplays;
	CGDirectDisplayID displays[0x10];
	CGGetOnlineDisplayList(0x10, displays, &nDisplays);
	
	for(int i=0; i<nDisplays; i++)
	{
		CGDirectDisplayID display = displays[i];
		{
			NSMenuItem* item;
			NSString* title = i ? [NSString stringWithFormat: @"Display %d", i+1] : @"Main Display";
			item = [[NSMenuItem alloc] initWithTitle: title action: nil keyEquivalent: @""];
			[item setEnabled: NO];
			[statusMenu addItem: item];
		}
		
		
		int mainModeNum;
		CGSGetCurrentDisplayMode(display, &mainModeNum);
		//modes_D4 mainMode;
		//CGSGetDisplayModeDescriptionOfLength(display, mainModeNum, &mainMode, 0xD4);
		ResMenuItem* mainItem = nil;
		
		
		int nModes;
		modes_D4* modes;
		CopyAllDisplayModes(display, &modes, &nModes);
		
		{
			NSMutableArray* displayMenuItems = [NSMutableArray new];
			//ResMenuItem* mainItem = nil;
			
			for(int j = 0; j <nModes; j++)
		    {
				ResMenuItem* item = [[ResMenuItem alloc] initWithDisplay: display andMode: &modes[j]];
				//[item autorelease];
				if(mainModeNum == j)
				{
					mainItem = item;
					[item setState: NSControlStateValueOn];
				}
				[displayMenuItems addObject: item];
				[item release];
			}
			int idealColorDepth = 32;
			double idealRefreshRate = 0.0f;
			if(mainItem)
			{
				idealColorDepth = [mainItem colorDepth];
				idealRefreshRate = [mainItem refreshRate];
			}
			[displayMenuItems sortUsingSelector: @selector(compareResMenuItem:)];
		
		
			NSMenu* submenu = [[NSMenu alloc] initWithTitle: @""];
			
			ResMenuItem* lastAddedItem = nil;
			for(int j=0; j < [displayMenuItems count]; j++)
			{
				ResMenuItem* item = [displayMenuItems objectAtIndex: j];
				if([item colorDepth] == idealColorDepth)
				{
					if([item refreshRate] == idealRefreshRate)
					{
						[item setTextFormat: 1];
					}
					
					if(lastAddedItem && [lastAddedItem width]==[item width] && [lastAddedItem height]==[item height] && [lastAddedItem scale]==[item scale])
					{
						double lastRefreshRate = lastAddedItem ? [lastAddedItem refreshRate] : 0;
						double refreshRate = [item refreshRate];
						if(!lastAddedItem || (lastRefreshRate != idealRefreshRate && (refreshRate == idealRefreshRate || refreshRate > lastRefreshRate)))
						{
							if(lastAddedItem)
							{
								[submenu removeItem: lastAddedItem];
								lastAddedItem = nil;
							}
							[submenu addItem: item];
							lastAddedItem = item;
						}
					}
					else
					{	
						[submenu addItem: item];
						lastAddedItem = item;
					}
				}
			}
			
			NSString* title;
			{
				if([mainItem scale] == 2.0f)
				{
					title = [NSString stringWithFormat: @"%d × %d ⚡️️", [mainItem width], [mainItem height]];
				}
				else
				{
					title = [NSString stringWithFormat: @"%d × %d", [mainItem width], [mainItem height]];
				}
			}
			
			
			NSMenuItem* resolution = [[NSMenuItem alloc] initWithTitle: title action: nil keyEquivalent: @""];
			[resolution setSubmenu: submenu];
			[submenu release];
			[statusMenu addItem: resolution];
			[resolution release];
			
			[displayMenuItems release];
		}
		
		{
			NSMutableArray* displayMenuItems = [NSMutableArray new];
			ResMenuItem* mainItem = nil;
			for(int j = 0; j < nModes; j++)
		    {
				ResMenuItem* item = [[ResMenuItem alloc] initWithDisplay: display andMode: &modes[j]];
				[item setTextFormat: 2];
				//[item autorelease];
				if(mainModeNum == j)
				{
					mainItem = item;
					[item setState: NSControlStateValueOn];
				}
				[displayMenuItems addObject: item];
				[item release];
			}
			int idealColorDepth = 32;
			double idealRefreshRate = 0.0f;
			if(mainItem)
			{
				idealColorDepth = [mainItem colorDepth];
				idealRefreshRate = [mainItem refreshRate];
			}
			[displayMenuItems sortUsingSelector: @selector(compareResMenuItem:)];
			
			
			NSMenu* submenu = [[NSMenu alloc] initWithTitle: @""];
			for(int j=0; j< [displayMenuItems count]; j++)
			{
				ResMenuItem* item = [displayMenuItems objectAtIndex: j];
				if([item colorDepth] == idealColorDepth)
				{
					if([mainItem width]==[item width] && [mainItem height]==[item height] && [mainItem scale]==[item scale])
					{
						[submenu addItem: item];
					}
				}
			}
			if(idealRefreshRate)
			{
				NSMenuItem* freq = [[NSMenuItem alloc] initWithTitle: [NSString stringWithFormat: @"%.0f Hz", [mainItem refreshRate]] action: nil keyEquivalent: @""];
			
				if([submenu numberOfItems] > 1)
				{
					[freq setSubmenu: submenu];
				}
				else
				{
					[freq setEnabled: NO];
				}
				[statusMenu addItem: freq];
				[freq release];
			}
			[submenu release];
			
			[displayMenuItems release];
			
		}
		
		
		free(modes);
		
		
		[statusMenu addItem: [NSMenuItem separatorItem]];
	}
	
	[statusMenu addItemWithTitle: @"About RDM" action: @selector(showAbout) keyEquivalent: @""];
	
	
	[statusMenu addItemWithTitle: @"Quit" action: @selector(quit) keyEquivalent: @""];
	[statusMenu setDelegate: self];
	[statusItem setMenu: statusMenu];
}


- (void) setMode: (ResMenuItem*) item
{
	CGDirectDisplayID display = [item display];
	int modeNum = [item modeNum];
	
	SetDisplayModeNum(display, modeNum);
	/*
	
	CGDisplayConfigRef config;
    if (CGBeginDisplayConfiguration(&config) == kCGErrorSuccess) {
        CGConfigureDisplayWithDisplayMode(config, display, mode, NULL);
        CGCompleteDisplayConfiguration(config, kCGConfigureForSession);
    }*/
	[self refreshStatusMenu];
}

- (void) applicationDidFinishLaunching: (NSNotification*) notification
{
//	NSLog(@"Finished launching");
	statusItem = [[[NSStatusBar systemStatusBar] statusItemWithLength: NSSquareStatusItemLength] retain];
	
	NSImage* statusImage = [NSImage imageNamed: @"StatusIcon"];
	[statusItem.button setImage: statusImage];
	[statusItem.button.cell setHighlightsBy: NSPushInCellMask];

  BOOL supportsDarkMenu = !(floor(NSAppKitVersionNumber) < 1343);  // NSAppKitVersionNumber10_10
  if (supportsDarkMenu) {
    [[statusItem.button image] setTemplate:YES];
  }

	[self refreshStatusMenu];
	
}

@end

试试效果:

完美,效果OK,其实看提示也能修改,但是笔者毕竟没写过object-c代码。

总结

这次使用AI把开源的RDM软件实现了ARM编译,借助AI修改了其中utils.h文件实现了原生M芯片应用,毕竟macOS 26之后要废弃转移x86的能力,证明了AI在小项目的强大之处,如果项目复杂,笔者即使使用AI也搞不定,毕竟不懂桌面APP的开发。

附上笔者编译的app附件,见文章附件

相关推荐
BigDark的笔记5 小时前
【ARM汇编】0x01_ARM和C混合编程实现基本运算
c语言·汇编·arm开发
路溪非溪6 小时前
Linux下iw工具的使用总结
linux·网络·arm开发·驱动开发
路溪非溪9 小时前
关于Linux中的日志问题
linux·arm开发·驱动开发
与遨游于天地1 天前
从 BPF 到 eBPF:一场 Linux 内核的“可编程”革命
linux·运维·arm开发
Chuncheng's blog1 天前
Ubuntu 24.04 ISO国内镜像下载(ARM / AMD64)
arm开发·ubuntu
忆和熙2 天前
ARMv8异常的类型与处理
arm开发·arm异常
EnglishJun2 天前
ARM嵌入式学习(二) --- 入门51(中断)
arm开发·学习
头发够用的程序员3 天前
GPU 流水线底层探索:从 SIMT 前端到 SIMD 后端的全链路解析
arm开发·人工智能·嵌入式硬件·深度学习·硬件架构·边缘计算
梁洪飞3 天前
armv7a和uboot里面的重要概念
arm开发·嵌入式硬件·arm