----------2015/01/09/23:21更新-----------------------------------

关于保留DEBUG信息的一个简单例子,见这篇随笔

----------2014/12/18/17:53更新-----------------------------------

前段时间写了这篇随笔,现在回过头来看感觉有很多问题,因此打算修正和补充一下,以前写的内容也没删,就留在这篇随笔的最下面了,可以对比着看看

目的:编写使用ZThread库的多线程程序

Windows: (Win7)

因为ZThread是支持Windows平台的,所以windows下,最好用visual studio的编译器,确保最好的兼容性

安装visual studio之后,通过开始>所有程序>Visual Studio 2013>Visual Studio Tools>VS2013 开发人员命令提示就可以使用CL、LINK、LIB、NMAKE这几个Windows下的编译和生成工具了。(相当于GNU的g++、ar、make)。

编译ZThread

从sourceforge.net下载ZThread-2.3.2.tar.gz,解压到F:/libs/ZThread-2.3.2

查看README>查看BUILDING

* Any other method is up to you. There are simply too many compilers,
too many versions and too many platforms to maintain separate build files
for.

BUT, this doesn't mean you are out of luck.

I have structured the code so that it is very simple to compile the library
however suits your needs best. All you need to do is include the .cxx files
in the src/ directory (not the subdirectories) in your build rule, and add the
include directory to your compilers include/ path.

打开terminal,切换到目录F:/libs/ZThread-2.3.2/src

输入命令:CL /c /I..\include *.cxx

  也就是编译所有的cxx文件,并生成对应的obj文件,但是不调用LINK对obj文件进行链接(比如somebody.cxx会被编译为somebody.obj)

  等价于GNU的:g++ -c -I ../include *.cxx

然后输入命令:LIB /OUT:ZThread_win32.lib *.obj

  也就是将所有的obj文件打包为lib文件

  等价于GNU的:ar -r ZThread.a *.o

  注意此处必须用CL编译的obj文件,并且由LIB打包成lib文件,如果是其他编译器编译的.a文件,你改后缀名改成.lib在windows下是用不了的,会报很多undefined reference to xxx错误。总而言之你坚持一个原则:用GNU的工具生成的库,那么引用这个库的代码就必须用GNU的编译器来编译,如果是用windows的工具生成的库,那么引用这个库的代码就必须用windows的编译器来编译!一般来说,如果一个库只使用C++ Standard里面的东西,就是平台无关的,比如ZThread就是这样的库,这样的库在几乎任何支持C++ Standard的平台上都是可以编译的,只不过,你选择了哪个平台,你最好就用哪个平台的编译器!

好,第二步,写代码,代码结构如下(加粗的就代表文件夹)

zthreaddemo

  libs

    zthread

      ZThread_win32.lib

  include

    zthread

      // zthread的所有头文件

    LiftOff.h

    Test.h

  src

    LiftOff.cpp

    Test.cpp

    main.cpp

  Makefile

代码我就不贴了,只贴Makefile的,你可以下载项目文件夹来看看

Makefile

# See
# http://msdn.microsoft.com/zh-cn/library/f35ctcxw.aspx
# for more info about Microsoft Visual C++ Compiler and Linker options # Microsoft Visual C++ Compiler && Linker tool
CC = cl
# Microsoft Visual C++ Linker
LINK = link # LIB_ZTHREAD is the ZThread static link library path
# /LIBPATH:<dir> Specifies a path that the linker will search before it searches the path specified in the LIB environment option. If you want to specify more than one directory, you must specify multiple /LIBPATH options.
# here we need the ZThread_win32.lib
LIB_ZTHREAD = /LIBPATH:libs\zthread # tells the linker where to find object files
OBJ_PATH = /LIBPATH:obj # '/I<PATH_NAME>' or '/I <PATH_NAME>' specifies a header search path
# for example: CL /I \xxinclude /I\my\include main.c
# tells the compiler where to find my own header files
# *** This makes you free from the burden to write things like #include "../include/xxx" in your cpp files ***
HEADER_PATH = /I include # See this page, search '/EHsc'
# http://wenku.baidu.com/view/04a34101de80d4d8d15a4ff2.html
EHSC = /EHsc # Compiles without linking.
COMPILATION_ONLY = /c # Compiler output object file: /Fo<PATH_NAME>, for example:
# cl /c hello.cpp /Foobj\hello.obj put the hello.obj file into the folder 'obj'
C_OUT = /Fo: # Linker output executable file
# note that the comma must be followed by the path WITHOUT any white-characters
L_OUT = /OUT: bin\test.exe: bin obj obj\main.obj obj\Test.obj obj\LiftOff.obj
$(LINK) $(LIB_ZTHREAD) $(OBJ_PATH) $(L_OUT)bin\test.exe main.obj Test.obj LiftOff.obj zthread_win32.lib
obj\main.obj: src\main.cpp include\Test.h
$(CC) $(EHSC) $(HEADER_PATH) $(COMPILATION_ONLY) src\main.cpp $(C_OUT)obj\main.obj obj\Test.obj: src\Test.cpp include\Test.h
$(CC) $(EHSC) $(HEADER_PATH) $(COMPILATION_ONLY) src\Test.cpp $(C_OUT)obj\Test.obj obj\LiftOff.obj: src\LiftOff.cpp include\LiftOff.h
$(CC) $(EHSC) $(HEADER_PATH) $(COMPILATION_ONLY) src\LiftOff.cpp $(C_OUT)obj\LiftOff.obj obj:
mkdir obj bin:
mkdir bin
# PHONY means 'clean' is a fake target
# use 'make clean' to remove all .obj files
# before rebuilding
# '-' means continue execute next command even if something goes wrong with this command
# type 'help' to get info about 'rmdir'
# type 'help rmdir' to get info about '/s' and '/q'
.PHONY: clean
clean:
-rmdir /s /q bin
-rmdir /s /q obj

这里面写了一些注释,看看可以帮助理解。总的思想就是:

先创建bin和obj文件夹,调用CL编译src里面的cpp文件,把生成的obj文件放到obj文件夹里,接着调用LINK链接所有的obj文件和lib文件,生成test.exe放到bin目录下.

要生成代码,所要做的工作就是打开VS2013 开发人员命令提示,然后切换到zthreaddemo目录中,输入命令nmake即可

里面有几个要点:

1、我将很多编译器和连接器的选项都写成了宏调用的形式,希望看起来可读性更好一些

2、注意文件的组织方式,src、include、libs、obj、bin这样的组织方式更整洁,src里面根据你的模块要求还可以设置子文件夹,include也是,libs里面根据你的需要也可以设置子文件夹,obj的组织结构一般与src是一一对应的(也就是说,如果你有src/xxx/yyy.cpp,那么生成obj文件的时候也应该有obj/xxx/yyy.obj)

3、类似于/OUT:这样的选项,冒号后面必须紧跟路径,中间不能有空格,而/I这个选项与路径之间,可以有空格也可以没空格

Linux: (Ubuntu)

编译ZThread,查看README, BUILDING

一般来说在类Unix环境下安装一个库的流程都是先./configure,再make,再make install。这样就可以

把头文件安装到/usr/local/include

把库文件(.a文件)安装到/usr/local/lib

把可执行文件安装到/usr/local/bin

但是我不知道是我的问题还是ZThread的configure代码的问题,./configure总是报错

所以我还是采取直接编译的方法,到/ZThread-2.3.2/src下运行命令g++ -I../include -fpermissive -c *.cxx

选项-fpermissive的作用是把一些error给改成warning.原因是ZThread的代码是比较陈旧的代码了,在目前的C++ Standard中过去的某些语法可能被编译器视为error,但是-fpermissive选项的意思就是告诉编译器:我确定这个代码格式没有语法或其他错误,只是比较陈旧不符合现代的标准而已。可以参考这个解释

选项-I../include是说zthread的头文件在上一级目录的include文件夹中

然后运行命令ar -r ZThread.a *.o

得到zthread.a

文件的组织方式仍然如前面所述

zthreaddemo

  libs

    zthread

      ZThread.a

  include

    zthread

      // zthread的所有头文件

    LiftOff.h

    Test.h

  src

    LiftOff.cpp

    Test.cpp

    main.cpp

  Makefile

下载项目文件夹

代码不变,只修改Makefile,如下所示(注意这里的Makefile与项目文件夹里的不太一样,以这里的为准)

# See
# http://www.gnu.org/software/gcc
# for more info about GNU C++ Compiler and Linker options # GNU C++ Compiler && Linker tool
CC = g++
# GNU C++ Linker
LINK = g++ # LIB_PATH tells the linker where to find library files
# -L <path> Specifies a path that the linker will search before it searches the path specified in the LIB environment option. If you want to specify more than one directory, you must specify multiple -L options.
# here we need the ZThread.a
LIB_PATH = -Llibs/zthread
# -l<LIBRARY_NAME> specifies a library file to link
# note that to use the '-l' flag, you must name
# your static library file libLIBRARY_NAME.a (the prefix 'lib'
# cannot be omitted) and use '-Ldir'
# before you actually using the '-l' flag, where 'dir'
# is the directory that your libxxx.a can be found
# immediately (can't be parent directory).
# You might think that it's verbose to say '-Llibs/zthread -lZThread',
# why not just say 'libs/zthread/ZThread.a' ?
# Yes in this case it's not a good example. But what if
# you put all your library files DIRECTLY in the folder 'libs'?
# Suppose you put libraryA.a libraryB.a libraryC.a DIRECTLY
# in the folder 'libs', you just need to specify '-Llibs' once,
# then you just say '-llibraryA' '-llibraryB' '-libraryC' to link
# all three library files.
LIB_FILE = -l # '-I<PATH_NAME>' specifies a header search path
# for example: g++ -I /xxinclude -I /my/include main.c
# tells the compiler where to find my own header files
# *** This makes you free from the burden to write things like #include "../include/xxx" in your cpp files ***
HEADER_PATH = -Iinclude # Compiles without linking.
COMPILATION_ONLY = -c # Compiler output object file: -o <PATH_NAME/object_file.o>, for example:
# g++ -c hello.cpp -o obj/hello.o put the hello.o file into the folder 'obj'
C_OUT = -o # Linker output executable file
L_OUT = -o bin/test: bin obj obj/main.o obj/Test.o obj/LiftOff.o
$(LINK) obj/main.o obj/Test.o obj/LiftOff.o $(LIB_PATH) -lZThread -lpthread $(L_OUT) bin/test
obj/main.o: src/main.cpp include/Test.h
$(CC) $(HEADER_PATH) $(COMPILATION_ONLY) src/main.cpp $(C_OUT) obj/main.o obj/Test.o: src/Test.cpp include/Test.h
$(CC) $(HEADER_PATH) $(COMPILATION_ONLY) src/Test.cpp $(C_OUT) obj/Test.o obj/LiftOff.o: src/LiftOff.cpp include/LiftOff.h
$(CC) $(HEADER_PATH) $(COMPILATION_ONLY) src/LiftOff.cpp $(C_OUT) obj/LiftOff.o obj:
mkdir obj bin:
mkdir bin
# PHONY means 'clean' is a fake target
# use 'make clean' to remove all .obj files
# before rebuilding
# '-' means continue execute next command even if something goes wrong with this command
# type 'rm --help' to get info about '-r' and '-f'
.PHONY: clean
clean:
-rm -r -f bin
-rm -r -f obj

---------------------------------------

2014/12/18更新之前的内容(已陈旧,有部分误区。尽量别看这个)

用mingw32-make就行了,语法跟GNU make基本上是一样的,只是要针对windows写命令,比如linux下的rm指令(删除文件)在windows下需要换成del指令

为什么不用Cygwin?——老爱报些莫名其妙的错误。下面举个例子

下面用LIB_ZTHREAD代指Windows下的F:/libs/zthread_win32.a或者Ubuntu下的/home/admin/libs/zthread.a

用HEADER_ZTHREAD代指Windows下的F:/libs/ZThread-2.3.2/include或者Ubuntu下的/home/admin/libs/ZThread-2.3.2/include

点此下载zthread_win32.a

点此下载zthread.a

文件结构:所有的.cpp文件.h文件Makefile都在一个文件夹里,假设其目录为TEST_DIR

源代码:

main.cpp

 #include "Test.h"

 using namespace std;

 int main()
{
Test::testLiftOff();
return ;
}

Test.h

 #ifndef TEST_H
#define TEST_H class Test
{
public:
static void testLiftOff(); private:
Test();
~Test();
}; #endif // TEST_H

Test.cpp

 #include "Test.h"

 #include "LiftOff.h"

 #include <zthread/Thread.h>

 #include <iostream>       // std::cout

 void Test::testLiftOff()
{
using namespace ZThread; try {
for (int i = ; i < ; ++i)
{
Thread th(new LiftOff(, i));
}
std::cout << "waiting for lift off" << std::endl;
} catch (Synchronization_Exception &e) {
std::cerr << e.what() << std::endl;
}
} Test::Test()
{
//ctor
} Test::~Test()
{
//dtor
}

LiftOff.h

 #ifndef LIFTOFF_H
#define LIFTOFF_H #include <zthread/Runnable.h> class LiftOff : public ZThread::Runnable
{
public:
LiftOff(int countDown_, int id_);
~LiftOff();
void run();
private:
int countDown;
int id;
}; #endif // LIFTOFF_H

LiftOff.cpp

 #include "LiftOff.h"

 #include <iostream>

 using namespace std;

 LiftOff::LiftOff(int countDown_, int id_)
:countDown(countDown_), id(id_)
{
// do nothing
} LiftOff::~LiftOff()
{
cout << "LiftOff" << id << " destroyed" << endl;
} void LiftOff::run()
{
while (countDown--)
cout << id << " count: " << countDown << endl;
cout << id << "LiftOff!" << endl;
}

1. Ubuntu (linux) + GNU make

Makefile

 # ZTHREAD_A the static link library file of ZThread
ZTHREAD_A = /home/admin/libs/zthread.a # ZTHREAD_H is the directory that has all the header
# files of the ZThread library
ZTHREAD_H = /home/admin/libs/ZThread-2.3.2/include
test.exe: main.o Test.o LiftOff.o
g++ -o test.exe main.o Test.o LiftOff.o -s $(ZTHREAD_A) -lpthread # -lpthread is necessary to link pthread library, which is not part of the default library in Ubuntu, ZThread need pthread support
main.o: main.cpp
g++ -c main.cpp -o main.o
# '-I' specifies the header search directory
Test.o: Test.cpp Test.h
g++ -I $(ZTHREAD_H) -c Test.cpp -o Test.o
LiftOff.o: LiftOff.cpp LiftOff.h
g++ -I $(ZTHREAD_H) -c LiftOff.cpp -o LiftOff.o # PHONY means 'clean' is a fake target
# use 'make clean' to remove all .o files
# before rebuilding
.PHONY: clean
clean:
-rm test # '-' means continue execute next command even if something goes wrong
-rm *.o

make clean

make -f Makefile

运行成功

2. Windows + mingw32-make

Makefile

 # ZTHREAD_A the static link library file of ZThread
ZTHREAD_A = F:/libs/ZThread-2.3./lib/zthread_win32.a
# ZTHREAD_H is the directory that has all the header
# files of the ZThread library
ZTHREAD_H = F:/libs/ZThread-2.3./include test.exe: main.o Test.o LiftOff.o
g++ -o test.exe main.o Test.o LiftOff.o -s $(ZTHREAD_A)
main.o: main.cpp
g++ -c main.cpp -o main.o
# '-I' specifies the header search directory
Test.o: Test.cpp Test.h
g++ -I $(ZTHREAD_H) -c Test.cpp -o Test.o
LiftOff.o: LiftOff.cpp LiftOff.h
g++ -I $(ZTHREAD_H) -c LiftOff.cpp -o LiftOff.o # PHONY means 'clean' is a fake target
# use 'make clean' to remove all .o files
# before rebuilding
# '-' means continue execute next command even if something goes wrong with this command
.PHONY: clean
clean:
-del test.exe
-del *.o

mingw32-make clean

mingw32-make -f Makefile

运行成功

3. Windows + Cygwin

Makefile

 # ZTHREAD_A the static link library file of ZThread
ZTHREAD_A = F:/libs/ZThread-2.3./lib/zthread_win32.a
# ZTHREAD_H is the directory that has all the header
# files of the ZThread library
ZTHREAD_H = F:/libs/ZThread-2.3./include test.exe: main.o Test.o LiftOff.o
g++ -o test.exe main.o Test.o LiftOff.o -s $(ZTHREAD_A)
main.o: main.cpp
g++ -c main.cpp -o main.o
# '-I' specifies the header search directory
Test.o: Test.cpp Test.h
g++ -I $(ZTHREAD_H) -c Test.cpp -o Test.o
LiftOff.o: LiftOff.cpp LiftOff.h
g++ -I $(ZTHREAD_H) -c LiftOff.cpp -o LiftOff.o # PHONY means 'clean' is a fake target
# use 'make clean' to remove all .o files
# before rebuilding
# '-' means continue execute next command even if something goes wrong with this command
.PHONY: clean
clean:
-rm test.exe
-rm *.o

make clean没问题

make报错(貌似是找不到__assert的实现,真心无语),报错的详细信息见这篇随笔

在Windows下使用nmake+Makefile+编译ZThread库(附例子)的更多相关文章

  1. windows下如何使用makefile编译

    1. 编写makefile. 2. 使用nmake进行编译, vs2010或者其他都是用nmake进行编译的,将bin目录添加到path环境变量中 先执行vcvars32.bat 再执行nmake

  2. 在Windows下搭建C++11 编译环境(附下载,包括mingw-build,TDM-GCC, nuwen MinGW Distro)

    由于现实的一些原因,并不是所有人都能很方便的享受到C++11 特性.特别是C++ Primer 第五版 和 The C++ Programming Language 第四版等全面C++ 11 铺开以后 ...

  3. 在Windows下使用MinGW静态编译Assimp

    使用MinGW静态编译Assimp 到了5月份了,没有写一篇日志,于是自己从知识库里面拿出一篇文章充数吧.这次将要解说怎样在Windows下使用MinGW静态编译Assimp. Assimp是眼下比較 ...

  4. 在Windows下使用CodeBlock使用libiconv第三方库

    在Windows下使用CodeBlock使用libiconv第三方库 1.         选择在Project->Build options下: 2.         如下图添加libicon ...

  5. 【VS开发】【数据库开发】libevent windows下基于VS2010的编译

    libevent是一个常用的网络库,下面就看看在windows下面编译测试的过程吧. 一 环境 系统:win8.1编译器:VS2013官方下载地址:http://libevent.org/版本:2.0 ...

  6. 开源项目:windows下使用MinGW+msys编译ffmpeg

    本文参考了网络上的不少文章,但由于版本环境的问题参考文章并不能直接指导编译,本文吸收多方经验,并在自己多次编译实验的基础上写成,欢迎转载,请注名出处.    FFmpeg是在Linux平台下开发的,但 ...

  7. windows 下使用 MinGW + msys 编译 ffmpeg

    本文参考了网络上的不少文章,但由于版本环境的问题参考文章并不能直接指导编译,本文吸收多方经验,并在自己多次编译实验的基础上写成,欢迎转载,请注名出处.    FFmpeg是在Linux平台下开发的,但 ...

  8. Windows下Visual studio 2013 编译 Audacity

    编译的Audacity版本为2.1.2,由于实在windows下编译,其源代码可以从Github上取得 git clone https://github.com/audacity/audacity. ...

  9. 几款比较好用的C语言的集成开发环境及在windows下用命令行编译C代码

    最近要用到C,所以尝试了这几款windows平台下比较好的IDE. VS2015:比较复杂和庞大,据说从2013版本开始支持C99标准. C-free:轻巧,但是不支持C99. vc++6.0:很多学 ...

随机推荐

  1. ecshop ecmall shopex

    ecshop 是一个B2C商城 适合企业及个人快速构建个性化网上商店.系统是基于PHP语言及MYSQL数据库构架开发的跨平台开源程序.(如沃购网)  山大路是dedecms ecmall(ECMall ...

  2. About stats collected

    pg_class.relpages pg_class.reltuples仅仅是近似值,和实际数据会有点误差: 新建空表.首次insert对自己主动收集和更新统计信息,影响的表pg_class\pg_s ...

  3. 如何修改JComboBox的宽度

    代码: String[] arr={"http://itts.ihe.ufo.com/rtts/ws.jsp","http://ittsstg.ihe.ufo.com/r ...

  4. Solidworks如何自动打开和关闭特征识别FeatureWorks

    如果直接对已有的零件识别特征,可能会报错   删除多余的特征,先只保留一个输入(注意没有必要连草图也删掉,草图不会影响识别特征,你识别完了之后草图再接着该拉伸拉伸,该切除切除),然后再次执行识别特征, ...

  5. js 立即执行函数定义方法

    <!DOCTYPE html> <html lang="zh"> <head> <meta charset="UTF-8&quo ...

  6. gitlab和github区别

    1.概述: github  是一个基于git实现在线代码托管的仓库,向互联网开放,企业版要收钱.gitlab   类似 github,一般用于在企业内搭建git私服,要自己搭环境. 2.GitHub. ...

  7. 坑爹的Adprep32.exe

    今天看书的时候,看到用ADSI设置Universal Group Membership Caching,就想到用.Net Framework来实现,找了半天,才找到System.directoryse ...

  8. 一直加载“fonts.googleapis.com”的解决办法

    原文:http://www.tuicool.com/articles/6bayeq 最近国内对google又开始了新一轮的屏蔽,很多wordpress用户发现一个现象,那就是网站前台和后台打开都非常慢 ...

  9. 如何为Drupal缓存对象指定缓存类?

    什么意思?意思是说,假如你有这样的需求,需要将cache_page缓存到数据库,其它的都缓存到memcache,这该怎么办? 看看_cache_get_object()的实现你就会知道上面的问题该怎么 ...

  10. docker build 的 cache 机制

    cache 机制注意事项 可以说,cache 机制很大程度上做到了镜像的复用,降低存储空间的同时,还大大缩短了构建时间.然而,不得不说的是,想要用好 cache 机制,那就必须了解利用 cache 机 ...