两层Makefile的书写方法,可以一次生成在X86和ARM运行的程序
2013-08-11 22:17
806 查看
首先,看下整个工程文件的结构图:
(1)主文件包含一个Makefile,一起对应的c源文件,还有子文件夹arm_client
![](http://img.blog.csdn.net/20130811215710140?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvbWFzaGFuZzEyMzQ1Njc4OQ==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)
(2)子文件夹arm_client
![](http://img.blog.csdn.net/20130811215643812?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvbWFzaGFuZzEyMzQ1Njc4OQ==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)
(3)先看一下子文件夹arm_client各个文件的内容:
client.c
Makefile文件
Makefile文件依靠的是三个文件:client.c,还有上一级目录的wrap.c和wrap.h
不理解这个makefile写法的原理请参考我上篇文章:Makefile:依赖多个c文件的书写方式
/article/7877140.html
(4)主文件各文件的内容
wrap.h
wrap.c
server.c
Makefile文件
第一:生成能在X86上运行的server可执行文件
第二:生成能在ARM上运行的client可执行文件,并吧client从arm_client文件里面复制到当前文件夹
(1)主文件包含一个Makefile,一起对应的c源文件,还有子文件夹arm_client
(2)子文件夹arm_client
(3)先看一下子文件夹arm_client各个文件的内容:
client.c
/* client.c [root@FriendlyARM /home]# ./client Response from server: TCP TRANSPORTATION TEST! */ #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <sys/socket.h> #include <netinet/in.h> #include "../wrap.h" #define MAXLINE 80 #define SERV_PORT 8888 int main(int argc, char *argv[]) { struct sockaddr_in servaddr; char buf[MAXLINE]; int sockfd, n; char *str="TCP transportation test!"; sockfd = Socket(AF_INET, SOCK_STREAM, 0); bzero(&servaddr, sizeof(servaddr)); servaddr.sin_family = AF_INET; inet_pton(AF_INET, "192.168.1.108", &servaddr.sin_addr); servaddr.sin_port = htons(SERV_PORT); Connect(sockfd, (struct sockaddr *)&servaddr, sizeof(servaddr)); Write(sockfd, str, strlen(str)); n = Read(sockfd, buf, MAXLINE); printf("Response from server:\n"); Write(STDOUT_FILENO, buf, n); printf("\n"); Close(sockfd); return 0; }
Makefile文件
CC = gcc ARMCC = arm-linux-gcc OTHER_HEADER = ../wrap.h OTHER_SOURCE = ../wrap.c all: client client: client.c arm_wrap.o $(ARMCC) -o $@ client.c arm_wrap.o arm_wrap.o: $(OTHER_SOURCE) $(OTHER_HEADER) $(ARMCC) -c -o $@ $(OTHER_SOURCE) clean: rm -f *.a *.o server client *~说明:
Makefile文件依靠的是三个文件:client.c,还有上一级目录的wrap.c和wrap.h
不理解这个makefile写法的原理请参考我上篇文章:Makefile:依赖多个c文件的书写方式
/article/7877140.html
(4)主文件各文件的内容
wrap.h
#ifndef _WRAP_H #define _WRAP_H /* #include <termios.h> #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <termios.h> #include <errno.h> #include <pthread.h> #include <string.h> #include <ctype.h> */ #include <stdlib.h> #include <errno.h> #include <sys/socket.h> void perr_exit(const char *s); int Accept(int fd, struct sockaddr *sa, socklen_t *salenptr); int Accept(int fd, struct sockaddr *sa, socklen_t *salenptr); void Bind(int fd, const struct sockaddr *sa, socklen_t salen); void Connect(int fd, const struct sockaddr *sa, socklen_t salen); void Listen(int fd, int backlog); int Socket(int family, int type, int protocol); ssize_t Read(int fd, void *ptr, size_t nbytes); ssize_t Write(int fd, const void *ptr, size_t nbytes); void Close(int fd); ssize_t Readn(int fd, void *vptr, size_t n); ssize_t Writen(int fd, const void *vptr, size_t n); static ssize_t my_read(int fd, char *ptr); ssize_t Readline(int fd, void *vptr, size_t maxlen); #endif
wrap.c
/* #include <stdlib.h> #include <errno.h> #include <sys/socket.h> */ #include "wrap.h" void perr_exit(const char *s) { perror(s); exit(1); } int Accept(int fd, struct sockaddr *sa, socklen_t *salenptr) { int n; again: if ( (n = accept(fd, sa, salenptr)) < 0) { if ((errno == ECONNABORTED) || (errno == EINTR)) goto again; else perr_exit("accept error"); } return n; } void Bind(int fd, const struct sockaddr *sa, socklen_t salen) { if (bind(fd, sa, salen) < 0) perr_exit("bind error"); } void Connect(int fd, const struct sockaddr *sa, socklen_t salen) { if (connect(fd, sa, salen) < 0) perr_exit("connect error"); } void Listen(int fd, int backlog) { if (listen(fd, backlog) < 0) perr_exit("listen error"); } int Socket(int family, int type, int protocol) { int n; if ( (n = socket(family, type, protocol)) < 0) perr_exit("socket error"); return n; } ssize_t Read(int fd, void *ptr, size_t nbytes) { ssize_t n; again: if ( (n = read(fd, ptr, nbytes)) == -1) { if (errno == EINTR) goto again; else return -1; } return n; } ssize_t Write(int fd, const void *ptr, size_t nbytes) { ssize_t n; again: if ( (n = write(fd, ptr, nbytes)) == -1) { if (errno == EINTR) goto again; else return -1; } return n; } void Close(int fd) { if (close(fd) == -1) perr_exit("close error"); } ssize_t Readn(int fd, void *vptr, size_t n) { size_t nleft; ssize_t nread; char *ptr; ptr = vptr; nleft = n; while (nleft > 0) { if ( (nread = read(fd, ptr, nleft)) < 0) { if (errno == EINTR) nread = 0; else return -1; } else if (nread == 0) break; nleft -= nread; ptr += nread; } return n - nleft; } ssize_t Writen(int fd, const void *vptr, size_t n) { size_t nleft; ssize_t nwritten; const char *ptr; ptr = vptr; nleft = n; while (nleft > 0) { if ( (nwritten = write(fd, ptr, nleft)) <= 0) { if (nwritten < 0 && errno == EINTR) nwritten = 0; else return -1; } nleft -= nwritten; ptr += nwritten; } return n; } static ssize_t my_read(int fd, char *ptr) { static int read_cnt; static char *read_ptr; static char read_buf[100]; if (read_cnt <= 0) { again: if ( (read_cnt = read(fd, read_buf, sizeof(read_buf))) < 0) { if (errno == EINTR) goto again; return -1; } else if (read_cnt == 0) return 0; read_ptr = read_buf; } read_cnt--; *ptr = *read_ptr++; return 1; } ssize_t Readline(int fd, void *vptr, size_t maxlen) { ssize_t n, rc; char c, *ptr; ptr = vptr; for (n = 1; n < maxlen; n++) { if ( (rc = my_read(fd, &c)) == 1) { *ptr++ = c; if (c == '\n') break; } else if (rc == 0) { *ptr = 0; return n - 1; } else return -1; } *ptr = 0; return n; }以上两个文件被编译的两次,在子文件里面被编译成目标文件arm_wrap.o,在主文件里面被编译成wrap.o
server.c
/* server.c bind error: Address already in use 发生这种问题是由于端口被程序绑定而没有释放造成. 可以使用netstat -lp命令查询当前处于连接的程序以及对应的进程信息。 然后用ps pid 察看对应的进程,并使用kill pid 关闭该进程即可。 */ #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <sys/socket.h> #include <netinet/in.h> #include "wrap.h" #define MAXLINE 80 #define SERV_PORT 8888 int DEBUG=1; int main(void) { struct sockaddr_in servaddr, cliaddr; socklen_t cliaddr_len; int listenfd, connfd; char buf[MAXLINE]; char str[INET_ADDRSTRLEN]; int i, n; listenfd = Socket(AF_INET, SOCK_STREAM, 0);//open a network connection(IPV4 ,TCP) if(DEBUG){ int on=1;//允许地址重用,端口可以马上重用 setsockopt(listenfd, SOL_SOCKET,SO_REUSEADDR, &on, sizeof(on) ); } bzero(&servaddr, sizeof(servaddr));//clear the struct servaddr.sin_family = AF_INET; servaddr.sin_addr.s_addr = htonl(INADDR_ANY); servaddr.sin_port = htons(SERV_PORT); Bind(listenfd, (struct sockaddr *)&servaddr, sizeof(servaddr));//bind servaddr to socket Listen(listenfd, 20);//The maximum of clients who are waiting for connection is 20 printf("Accepting connections ...\n"); while (1) { cliaddr_len = sizeof(cliaddr);//cliaddr_len 是传入传出参数,每次调用accept前重新赋初值 connfd = Accept(listenfd, (struct sockaddr *)&cliaddr, &cliaddr_len); n = Read(connfd, buf, MAXLINE); printf("received from %s at Client PORT %d\n", inet_ntop(AF_INET, &cliaddr.sin_addr, str, sizeof(str)), ntohs(cliaddr.sin_port));//客户端的端口号是自动分配的 printf("Response from client:\n"); Write(STDOUT_FILENO, buf, n); printf("\n"); for (i = 0; i < n; i++){ //printf("%x",buf[i]);// if add this ,bind error buf[i] = toupper(buf[i]);//把收到的字符转换成大写字母发回去 } Write(connfd, buf, n); Close(connfd); } }
Makefile文件
CC = gcc ARMCC = arm-linux-gcc all: server client client: wrap.h make -C arm_client/ all CC=$(ARMCC) cp arm_client/client . server: server.c wrap.o $(CC) -o server server.c wrap.o wrap.o: wrap.c wrap.h $(CC) -c -o $@ wrap.c clean: make -C arm_client/ $@ rm -f *.a *.o server client *~这个Makefile文件做两件事:
第一:生成能在X86上运行的server可执行文件
第二:生成能在ARM上运行的client可执行文件,并吧client从arm_client文件里面复制到当前文件夹
相关文章推荐
- vc++生成程序不需要.net运行环境的可以执行exe程序的方法
- C程序访问hadoop出现的各种编译错误和运行时各种类DefFound异常的解决方法(makefile的书写和环境变量的配置)
- c# 程序只运行一次的处理方法
- FreePascal - CodeTyphon交叉编译,在一个操作系统生成各个操作系统可以运行的程序!
- 定义一个“点”(Point)类用来表示三维空间中的点(有三个坐标)。要求如下: (1)可以生成具有特定坐标的点对象。 (2)提供可以设置三个坐标的方法。 (3)提供可以计算该“点”距原点距离平方的方法。 (4)编写主类程序验证。
- Android模拟器Genymotion添加ARM程序运行环境的方法
- 6个可以隐藏运行bat,浏览器等程序的方法
- 使用installanywhere打包java文件生成任何平台都可以运行的程序(如.exe)(关闭360!)
- Android 应用第一次运行时,引导页面的设置方法(只让程序Acitivity运行一次的设置方法)
- WinCE下面运行程序时只能运行一次的方法
- C# 程序只运行一次的处理方法
- 一个简单的执行程序的GNU automake自动生成Makefile的方法及案例
- 如何编译可以在arm平台上运行的可执行程序?
- C++可以用的计算程序运行时间的方法
- 一个可以自动生成静态库,自动安装程序的Makefile
- Android 应用第一次运行时,引导页面的设置方法(只让程序Acitivity运行一次的设置方法)
- 程序只运行一次的方法
- 在Makefile动态生成程序版本号的方法
- binbinyang---Android 应用第一次运行时,引导页面的设置方法(只让程序Acitivity运行一次的设置方法)+SharedPreferences
- Android 应用第一次运行时,引导页面的设置方法(只让程序Acitivity运行一次的设置方法)