上一篇一步一步写一个简单通用的makefile(二) 里面的makefile 实现对通用的代码进行编译,这一章我将会对上一次的makefile 进行进一步的优化.

优化后的makefile:

#Hellomake
#Magnum, 2014-10-20
# 指令编译器和选项
CC=gcc
CFLAGS=-Wall
# 需要链接库的库名,比如libm.a,就是-lm,需要去掉前面的lib和后面的.a
LIBS=-lm
# 设置默认搜索头文件的路径,优先是这个,然后是系统路径
IncludeDir = -I./include/
# 需要链接的库的路径
LinkDir = #-L
OBJ_DIR = ./obj
BIN_DIR = ./bin #PROJECT_TOP_DIR 设置成pwd 或者"./"都行
PROJECT_TOP_DIR=$(shell pwd)#$(shell cd ../; pwd)
PROJECT_BIN_DIR=$(PROJECT_TOP_DIR)/bin
PROJECT_SRC_DIR=$(PROJECT_TOP_DIR)/src
PROJECT_LIB_DIR=$(PROJECT_TOP_DIR)/lib
PROJECT_OBJ_DIR=$(PROJECT_TOP_DIR)/objs
MKDIR := mkdir -p # 目标文件
EXE_NAME=hellomake
TARGET=$(BIN_DIR)/$(EXE_NAME) #源文件的文件类型
FILE_TYPE=c
src=$(wildcard $(PROJECT_SRC_DIR)/*.$(FILE_TYPE))
dir= $(notdir $(src))
PROJECT_OBJ= $(patsubst %.$(FILE_TYPE),%.o,$(dir) )
PROJECT_ALL_OBJS= $(addprefix $(PROJECT_OBJ_DIR)/, $(PROJECT_OBJ)) all: chdir $(TARGET)
@echo "magnum $(PROJECT_OBJ)"
@echo "magnum $(PROJECT_OBJ_DIR)"
@echo "magnum $(PROJECT_ALL_OBJS)" $(TARGET): $(PROJECT_ALL_OBJS)
$(CC) -o $@ $^ $(LinkDir) $(LIBS) chdir:
@if test ! -d $(PROJECT_OBJ_DIR) ; \
then \
mkdir $(PROJECT_OBJ_DIR) ; \
fi @if test ! -d $(PROJECT_BIN_DIR) ; \
then \
mkdir $(PROJECT_BIN_DIR) ; \
fi .PHONY : clean
clean:
-rm -rf $(PROJECT_BIN_DIR) $(PROJECT_OBJ_DIR) $(PROJECT_OBJ_DIR)/%.o:$(PROJECT_SRC_DIR)/%.$(FILE_TYPE)
$(CC) $(CFLAGS) -o $@ -c $< $(IncludeDir)

这个优化后的makefile 对于一般需要写一个小的测试程序都有一定的通用性,如果需要对新的程序进行修改:
1. 编译类型C用gcc, c++用g++

2. 源文件的路径 PROJECT_SRC_DIR

3. 文件类型c 还是cpp

4. 还有这三个:

# 需要链接库的库名,比如libm.a,就是-lm,需要去掉前面的lib和后面的.a
LIBS=-lm
# 设置默认搜索头文件的路径,优先是这个,然后是系统路径
IncludeDir = -I./include/
# 需要链接的库的路径
LinkDir = #-L

下面我就用这个模板去编译一个opencl的小程序。

文件树如下:

.
├── convolve.cl
├── convolve_cl.cpp
├── makefile
└── makefile~

很简单的只有3个文件, convolve.cl, convolve_cl.cpp, makefile.

convolve_cl.cpp源码:

// newTutorial1.cpp : Defines the entry point for the console application.
// //#include "stdafx.h"
#include <CL/cl.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <iostream>
#include <fstream>
#include <string.h>
#include <string>
#include <pthread.h>
using namespace std;
#pragma comment (lib,"OpenCL.lib") #define WIDTH 1920
#define HEIGHT 1080
#define FRAMES 1
typedef unsigned char uint8_t; static double now_ms(void) {
struct timespec res;
clock_gettime(CLOCK_REALTIME, &res);
return 1000.0 * res.tv_sec + (double) res.tv_nsec / 1e6;
} static int filter0(uint8_t *src, uint8_t *dst, uint8_t *ocl, int w, int h) {
printf("filter 0 ,w=%d, h=%d\n",w, h);
double start, end;
int i =;
int j =;
if(w > WIDTH || h > HEIGHT)
return ;
//start = now_ms();
for (i = ; i < h - ; ++i) {
for (j = ; j < w - ; ++j) {
int index = j + i * w;
uint8_t lu = src[index - - w];
uint8_t lm = src[index - ];
uint8_t ld = src[index - + w];
uint8_t mu = src[index - w];
uint8_t mm = src[index];
uint8_t md = src[index + w];
uint8_t ru = src[index + - w];
uint8_t rm = src[index + ];
uint8_t rd = src[index + + w];
int sum = lu + lm + ld + mu + mm + md + ru + rm + rd;
// printf("%d, %d, %d, %d, %d, %d, %d %d, %d,\n",lu, lm, ld, mu, mm, md, ru, rm, rd);
dst[index] = (uint8_t)sum / + ;
// printf(" dst[%d] =%d",index, dst[index]);
if(ocl[index] != dst[index])
printf("index[%d] differ \n", index);
}
// printf("\n");
}
end = now_ms();
//printf("filter 0 %f \n", end - start);
return ;
} //°ÑÎıŸÎÄŒþ¶ÁÈëÒ»žöstringÖÐ
int convertToString(const char *filename, std::string& s)
{
size_t size;
char* str; std::fstream f(filename, (std::fstream::in | std::fstream::binary)); if(f.is_open())
{
size_t fileSize;
f.seekg(, std::fstream::end);
size = fileSize = (size_t)f.tellg();
f.seekg(, std::fstream::beg); str = new char[size+];
if(!str)
{
f.close();
return NULL;
} f.read(str, fileSize);
f.close();
str[size] = '\0'; s = str;
delete[] str;
return ;
}
printf("Error: Failed to open file %s\n", filename);
return ;
} int main(int argc, char* argv[])
{
int i, ret;
double start, end;
uint8_t * inputBuf;
uint8_t * dstBuf1;
uint8_t * dstBuf2;
inputBuf =(uint8_t *)malloc(WIDTH * HEIGHT * sizeof(uint8_t));
dstBuf1 =(uint8_t *)malloc(WIDTH * HEIGHT * sizeof(uint8_t));
dstBuf2 =(uint8_t *)malloc(WIDTH * HEIGHT * sizeof(uint8_t));
memset(dstBuf1,,WIDTH * HEIGHT * sizeof(uint8_t));
memset(dstBuf2,,WIDTH * HEIGHT * sizeof(uint8_t)); srand( (unsigned)time( NULL ) );
for(i = ; i < WIDTH * HEIGHT; i++) {
inputBuf[i] = rand()%;
//printf("[%d] =%d\n", i, inputBuf[i]);
} //return 0;
cl_uint status;
cl_platform_id platform; //ŽŽœšÆœÌš¶ÔÏó
status = clGetPlatformIDs( , &platform, NULL ); cl_device_id device; //ŽŽœšGPUÉ豞
clGetDeviceIDs( platform, CL_DEVICE_TYPE_GPU,
,
&device,
NULL);
cl_uint maxComputeUnits;
status = clGetDeviceInfo(device,CL_DEVICE_MAX_COMPUTE_UNITS,
sizeof(cl_uint),
&maxComputeUnits,
NULL);
printf("maxComputeUnits = %d\n" ,maxComputeUnits); //ŽŽœšcontext
cl_context context = clCreateContext( NULL,
,
&device,
NULL, NULL, NULL);
//ŽŽœšÃüÁî¶ÓÁÐ
cl_command_queue queue = clCreateCommandQueue( context,
device,
CL_QUEUE_PROFILING_ENABLE, NULL ); //ŽŽœšÈýžöOpenCLÄÚŽæ¶ÔÏó
cl_mem clinbuf = clCreateBuffer(context,
CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR,
WIDTH*HEIGHT*sizeof(cl_uchar),inputBuf,
NULL ); cl_mem cloutbuf = clCreateBuffer( context,
CL_MEM_WRITE_ONLY,
WIDTH*HEIGHT * sizeof(cl_uchar),
NULL, NULL ); const char * filename = "convolve.cl";
std::string sourceStr;
status = convertToString(filename, sourceStr);
const char * source = sourceStr.c_str();
size_t sourceSize[] = { strlen(source) }; //ŽŽœš³ÌÐò¶ÔÏó
cl_program program = clCreateProgramWithSource(
context,
,
&source,
sourceSize,
NULL);
//±àÒë³ÌÐò¶ÔÏó
status = clBuildProgram( program, , &device, NULL, NULL, NULL );
if(status != )
{
printf("clBuild failed:%d\n", status);
char tbuf[0x10000];
clGetProgramBuildInfo(program, device, CL_PROGRAM_BUILD_LOG, 0x10000, tbuf, NULL);
printf("\n%s\n", tbuf);
return -;
} cl_int dimx = WIDTH;
cl_int dimy = HEIGHT;
cl_event ev;
cl_kernel kernel;
cl_ulong startTime, endTime;
cl_ulong kernelExecTimeNs;
float *op_data = ; #if 1
//ŽŽœšKernel¶ÔÏó
kernel = clCreateKernel( program, "filter", NULL ); //ÉèÖÃKernel²ÎÊý clSetKernelArg(kernel, , sizeof(cl_mem), (void *)&clinbuf);
clSetKernelArg(kernel, , sizeof(cl_int), (void *)&dimx);
clSetKernelArg(kernel, , sizeof(cl_int), (void *)&dimy);
clSetKernelArg(kernel, , sizeof(cl_mem), (void *)&cloutbuf); //Set local and global workgroup sizes
size_t localws[] = {, } ;
size_t globalws[] = {WIDTH,HEIGHT}; //ÖŽÐÐkernel
clEnqueueNDRangeKernel(
queue ,kernel,
, , globalws, NULL,
, NULL, &ev); clFinish( queue );
//ŒÆËãkerenlÖŽÐÐʱŒä clGetEventProfilingInfo(ev, CL_PROFILING_COMMAND_START,
sizeof(cl_ulong), &startTime, NULL);
clGetEventProfilingInfo(ev, CL_PROFILING_COMMAND_END,
sizeof(cl_ulong), &endTime, NULL);
kernelExecTimeNs = endTime-startTime;
printf("kernal exec time :%8.6f ms\n ", kernelExecTimeNs*1e- ); //ÊýŸÝ¿œ»ØhostÄÚŽæ
cl_uchar *ptr;
ptr = (cl_uchar *) clEnqueueMapBuffer( queue,
cloutbuf,
CL_TRUE,
CL_MAP_READ,
,
WIDTH*HEIGHT * sizeof(cl_uchar),
, NULL, NULL, NULL );
//œá¹ûÑéÖ€£¬ºÍcpuŒÆËãµÄœá¹û±ÈœÏ start = now_ms();
for(i = ; i< FRAMES; i++) {
ret = filter0(inputBuf, dstBuf1, ptr,WIDTH, HEIGHT);
if(ret)
printf("filter Fail \n");
}
end = now_ms();
printf("filter 0 %f \n", (end - start)/FRAMES); //ÑéÖ€GPUŒÆËãœá¹û
/* for(i = 0; i < M*N; i++)
{
//printf("%d, %6.3f,%6.3f\n",i,outbuf[i],op_data[i]);
if(abs(dstBuf1[i] - dstBuf2[i]) > 0.0001)
{
printf("check failed\n");
break;
}
}
if(i == M*N)
printf("check passed\n"); */
#endif if(inputBuf)
free(inputBuf);
if(dstBuf1)
free(dstBuf1);
if(dstBuf2)
free(dstBuf2); //ÉŸ³ýOpenCL×ÊÔŽ¶ÔÏó
clReleaseMemObject(clinbuf);
clReleaseMemObject(cloutbuf);
clReleaseProgram(program);
clReleaseCommandQueue(queue);
clReleaseContext(context);
return ;
}

convolve.cl 源码:

#pragma OPENCL EXTENSION cl_amd_printf : enable

__kernel void filter( __global uchar* in, int Width, int Height, __global uchar* out)
{
// WIDTH
int row = get_global_id();
//HEIGHT
int col = get_global_id();
// int wi = get_global_size(0);
// int he = get_global_size(1);
// printf("Magnum Global w= %d, h= %d,row=%d, col =%d\n",wi,he,row,col);
if(row == || col == ||row == Width - || col == Height -)
return; int index = row + col * Width;
uchar lu = in[index - - Width];
uchar lm = in[index - ];
uchar ld = in[index - + Width];
uchar mu = in[index - Width];
uchar mm = in[index];
uchar md = in[index + Width];
uchar ru = in[index + - Width];
uchar rm = in[index + ];
uchar rd = in[index + + Width];
int sum = lu + lm + ld + mu + mm + md + ru + rm + rd;
out[index] = (uchar)sum / + ;
// printf("%d, %d, %d, %d, %d, %d, %d %d, %d,\n",lu, lm, ld, mu, mm, md, ru, rm, rd);
// printf("dst[%d] = %d\n", index, out[index]);
}

下面是修改上面给出的模板makefile文件,来编译这个程序:
1. 因为是cpp,所以CC=g++, FILE_TYPE=cpp
2. 可执行文件的名字:EXE_NAME=convolve_cl

3. 链接的库:

LIBS= -lOpenCL -lfreeimage -lrt
IncludeDir = -I/opt/AMDAPP/include
LinkDir = -L/opt/AMDAPP/lib/x86_64
修改后的makefile如下:

#Hellomake
#Magnum, --
# 指令编译器和选项
CC=g++
CFLAGS=-Wall
# 需要链接库的库名,比如libm.a,就是-lm,需要去掉前面的lib和后面的.a
LIBS= -lOpenCL -lfreeimage -lrt
# 设置默认搜索头文件的路径,优先是这个,然后是系统路径
IncludeDir = -I/opt/AMDAPP/include
# 需要链接的库的路径
LinkDir = -L/opt/AMDAPP/lib/x86_64
OBJ_DIR = ./obj
BIN_DIR = ./bin #PROJECT_TOP_DIR 设置成pwd 或者"./"都行
PROJECT_TOP_DIR=.#$(shell pwd)#$(shell cd ../; pwd)
PROJECT_BIN_DIR=$(PROJECT_TOP_DIR)/bin
PROJECT_SRC_DIR=$(PROJECT_TOP_DIR)/
PROJECT_LIB_DIR=$(PROJECT_TOP_DIR)/lib
PROJECT_OBJ_DIR=$(PROJECT_TOP_DIR)/objs
MKDIR := mkdir -p # 目标文件
EXE_NAME=convolve_cl
TARGET=$(BIN_DIR)/$(EXE_NAME) #源文件的文件类型
FILE_TYPE=cpp
src=$(wildcard $(PROJECT_SRC_DIR)/*.$(FILE_TYPE))
dir= $(notdir $(src))
PROJECT_OBJ= $(patsubst %.$(FILE_TYPE),%.o,$(dir) )
PROJECT_ALL_OBJS= $(addprefix $(PROJECT_OBJ_DIR)/, $(PROJECT_OBJ)) all: chdir $(TARGET)
@echo "magnum $(PROJECT_OBJ)"
@echo "magnum $(PROJECT_OBJ_DIR)"
@echo "magnum $(PROJECT_ALL_OBJS)" $(TARGET): $(PROJECT_ALL_OBJS)
$(CC) -o $@ $^ $(LinkDir) $(LIBS) chdir:
@if test ! -d $(PROJECT_OBJ_DIR) ; \
then \
mkdir $(PROJECT_OBJ_DIR) ; \
fi @if test ! -d $(PROJECT_BIN_DIR) ; \
then \
mkdir $(PROJECT_BIN_DIR) ; \
fi .PHONY : clean
clean:
-rm -rf $(PROJECT_BIN_DIR) $(PROJECT_OBJ_DIR) $(PROJECT_OBJ_DIR)/%.o:$(PROJECT_SRC_DIR)/%.$(FILE_TYPE)
$(CC) $(CFLAGS) -o $@ -c $< $(IncludeDir)

可以看到相比较之前的makefile只需要修改几个文件即可。
我的这个是ubuntu 环境 AMD显卡的opencl程序,虽然你们的环境有些不同,但是对于你们需要修改的编译程序也是同样适用的

一步一步写一个简单通用的makefile(三)的更多相关文章

  1. 一步一步写一个简单通用的makefile(一)

    经常会用写一些小的程序有的是作为测试,但是每次都需要写一些简单的GCC 命令,有的时候移植一些项目中的部分代码到小程序里面进行测试,这个时候GCC 命令并不好些,如果写啦一个比较常用的makefile ...

  2. [置顶] 自己写一个简单通用的Makefile

    转自:http://blog.csdn.net/u011913612/article/details/52102241 一.makefile的作用 Makefile是用于自动编译和链接的,一个工程有很 ...

  3. 一步一步写一个简单通用的makefile(四)--写一个通用的makefile编译android可执行文件

    通常要把我们自己的的代码编译成在android里面编译的可执行文件,我们通常是建一个文件夹 . ├── Android.mk ├── Application.mk ├── convolve.cl ├─ ...

  4. 一步一步写一个简单通用的makefile(二)

    这一篇源代码沿用上一篇的源代码hellomake.c hellofunc.c hellofunc.h makefile 但是代码内容和结构有变化,如下: . ├── include │   └── h ...

  5. (原创)如何使用boost.asio写一个简单的通信程序(一)

    boost.asio相信很多人听说过,作为一个跨平台的通信库,它的性能是很出色的,然而它却谈不上好用,里面有很多地方稍不注意就会出错,要正确的用好asio还是需要花一番精力去学习和实践的,本文将通过介 ...

  6. linux设备驱动第三篇:如何写一个简单的字符设备驱动?

    在linux设备驱动第一篇:设备驱动程序简介中简单介绍了字符驱动,本篇简单介绍如何写一个简单的字符设备驱动.本篇借鉴LDD中的源码,实现一个与硬件设备无关的字符设备驱动,仅仅操作从内核中分配的一些内存 ...

  7. 用node.js从零开始去写一个简单的爬虫

    如果你不会Python语言,正好又是一个node.js小白,看完这篇文章之后,一定会觉得受益匪浅,感受到自己又新get到了一门技能,如何用node.js从零开始去写一个简单的爬虫,十分钟时间就能搞定, ...

  8. linux设备驱动第三篇:写一个简单的字符设备驱动

          在linux设备驱动第一篇:设备驱动程序简介中简单介绍了字符驱动,本篇简单介绍如何写一个简单的字符设备驱动.本篇借鉴LDD中的源码,实现一个与硬件设备无关的字符设备驱动,仅仅操作从内核中分 ...

  9. 用C写一个简单的推箱子游戏(一)

    我现在在读大二,我们有一门课程叫<操作系统>,课程考查要求我们可以写一段程序或者写Windows.iOS.Mac的发展历程.后面我结合网上的资料参考,就想用自己之前简单学过的C写一关的推箱 ...

随机推荐

  1. android 开源框架推荐

    同事整理的 android 开源框架,个个都堪称经典.32 个赞! 1.volley 项目地址 https://github.com/smanikandan14/Volley-demo (1)  JS ...

  2. Php之Http请求urlencode/rawurlencode

    在http请求中,如果参数值带中文最好使用urlencode/rawurlencode函数. 如果参数值中带加号也最好使用,否则后台接收时,+号变成空格,引起不必要的麻烦. 注:urlencode和r ...

  3. ubuntu 下安装 apache php mysql

    ubuntu 安装 apache+php+mysql1.打开终端,输入“sudo apt-get install apache2”,回车;(安装apache2.0或2.x新版本,系统会自动查找新的版本 ...

  4. javascript 单行向上滚动文字

    <html><head><meta http-equiv="Content-Type" content="text/html; charse ...

  5. jquery中onclick="fn"中$(this)所代表的对象

    jquery中onclick="fn"中$(this)所代表的对象 js方法 function qiehuan(){ var src = $(this).attr("da ...

  6. 表格table样式布局设置

    <style> table{ border-collapse:collapse; margin:0 auto;} table tr td{ border:1px solid #000; l ...

  7. 摩尔斯电码(Morse Code)Csharp实现

    摩尔斯电码,在早期的"生产斗争"生活中,扮演了很重要的角色,作为一种信息编码标准,摩尔斯电码拥有其他编码方案无法超越的长久生命.摩尔斯电码在海事通讯中被作为国际标准一直使用到199 ...

  8. [转]EJS入门

    今天学习了EJS,转个再点个赞,动态创网页的好方法! 主页:http://www.embeddedjs.com/ 转自:http://www.csser.com/board/4fddc4f0b28ed ...

  9. gulp 中的增量编译

    最近花一点时间学了下 gulp,顺便学了下 sass,因为工作中并不需要用(我比较希望学习是需求驱动),所以一直拖到现在才学.突然觉得学习这类工具性价比很高,半天一天即可上手,技能树丰富了(尽管可能只 ...

  10. Http 状态码详解

    状态码 含义 100 客户端应当继续发送请求.这个临时响应是用来通知客户端它的部分请求已经被服务器接收,且仍未被拒绝.客户端应当继续发送请求的剩余部分,或者如果请求已经完成,忽略这个响应.服务器必须在 ...