关于cmake+mingw+yasm+vs 生成工程 编译代码问题总结

来源:互联网 发布:三国志11 mac 打不开 编辑:程序博客网 时间:2024/05/17 09:45

最近想写一个库,需要支持windows+linux,但是自己是活在windows下的人,所以就用mingw来代替linux,代码写完了,可是编译环境问题一堆,所以这里总结下。

一.准备工作

   安装好cmake,mingw 64位,yasm,msys,这些下载安装网上一堆,就不赘述了。环境变量什么的也需要都配好。

二.yasm编译器编译汇汇编代码运行,下面先贴代码hello.asm

global WinMainextern ExitProcess  ; external functions in system libraries extern MessageBoxAsection .data title:  db 'Win64', 0msg:    db 'Hello world!', 0section .textWinMain:    sub rsp, 28h      mov rcx, 0       ; hWnd = HWND_DESKTOP    lea rdx,[msg]    ; LPCSTR lpText    lea r8,[title]   ; LPCSTR lpCaption    mov r9d, 0       ; uType = MB_OK    call MessageBoxA    add rsp, 28h      mov  ecx,eax    call ExitProcess    hlt     ; never here

a.编译asm文件

 command:yasm hello.asm -fwin64

 会生成hello.obj

b.链接

  命令:gcc hello.obj -o test.exe

c.运行test.exe,系统是win7 64,mingw是64,yasm是64位,运行是会缺少一些库,缺啥就去找。kernel32.lib  libcmt.lib link.exe mspdb120.dll User32.lib


三,yasm+gcc互调

有时,我们写完代码之后,性能不佳,就想用汇编来优化代码,第二点纯属asm代码,没有c代码,新加一个例子,先贴代码,代码网上找的。

addone.asm

global addone           ;  addone: MOV RAX, [RSP + 20] ; stack top + 20 bytes      ADD RAX, 1      RET  


calladdone.c

#include <stdio.h>    int main(){    int a = 3;    printf("before call, a is %d.\n", a);    a = addone(a);    printf("after call, a is %d.\n", a);    return 0;  }  

a.进入mingw,编译汇编代码

 命令:yasm -felf64 addone.asm

会生成addone.o

b.编译c代码,链接

命令:gcc calladdone.c addone.o

c.执行文件


四,使用cmake

关于cmake的用法,网上也有入门的一些教程,本文主要针对yasm的一些用法,就拿第三点的例子,用camke来编译。

CMakeList.txt

project(test2)cmake_minimum_required (VERSION 2.8.8)find_package(Yasm)if(YASM_FOUND)    if (YASM_VERSION_STRING VERSION_LESS "1.2.0")        message(STATUS "Yasm version ${YASM_VERSION_STRING} is too old. 1.2.0 or later required")    else()        message(STATUS "Found Yasm ${YASM_VERSION_STRING} to build assembly primitives")    endif()else()message(STATUS "NOT Found Yasm========")endif()enable_language(ASM_YASM)set(ASM_SRC addone.asm)set(APP_SRC calladdone.c)#add_library(libaddone ${ASM_SRC})add_executable(addone ${APP_SRC} ${ASM_SRC})
本身可以考虑将addone.asm生成一个库文件,然后c文件去调;另一个就是直接连在一起生成可执行文件。

假如addone.asm calladdone.c CMakeLists.txt这三个文件一个目录,在该目录下创建一个build文件夹,进入到build目录中,

执行:cmake .. -G"MSYS Makefilse"  //注意 有两个点 是makelist的目录,执行完之后,再执行make就搞定

五,vs使用asm

 网上也有很多资源,注意汇编代码32,64的区别,很容易就编译出错


六,cmake 生成vs 2013(本文装的是2013)工程,并且集成yasm

cmake 生成vs 2013的命令是:cmake .. -G"Visual Studio 12 Win64"  // 两个点是cmakelist的路径

这个没有难度,要集成yasm也跟第四点一样,也没有难度,将带有汇编的代码编译成库,然后主程序去链接。

但是照常理生成之后,单独的library会有一个工程文件,主程序也有一个工程,单独在vs中编译library没有问题;

可是主程序链接到库文件进行编译时,就会链接不到;另外一点,如果是cmake .. -G"MSYS Makefiles"的话,直接执行命令是没有问题的,

只有在vs中,主程序链接库编译时出问题。

这里介绍一种方法,我也是初学者,也就知道这一种方法:

将asm相关的库文件生成为object 库 在cmakelist 中加:

if(MSVC_IDE OR XCODE)        # MSVC requires custom build rules in the main cmake script for yasm        set(MSVC_ASMS "${A_SRCS}" CACHE INTERNAL "yasm sources")        set(A_SRCS)endif() add_library(libcom OBJECT ${LIB_SRC} ${ASM_PRIMITIVES})      # ASM_PRIMITIVES是你的asm相关文件



在主程序的cmakelist文件中加:

    

 foreach(ASM ${MSVC_ASMS})        set(YASM_SRC ${ASM})message(${ASM})        list(APPEND YASM_SRCS ${YASM_SRC})        list(APPEND YASM_OBJS ${ASM}.${SUFFIX})        add_custom_command(            OUTPUT ${ASM}.${SUFFIX}            COMMAND ${YASM_EXECUTABLE} ARGS ${YASM_FLAGS} ${YASM_SRC} -o ${ASM}.${SUFFIX}            DEPENDS ${YASM_SRC})    endforeach()add_library(common-static STATIC $<TARGET_OBJECTS:libcom> ${YASM_OBJS} ${YASM_SRCS}) #这是新加入的add_executable(test ${APP_SRC} )   #这个是原先的


其他操作在网上查查,这样再cmake一下,进入到vs工程中去,编译执行。

楼主也是初学者,欢迎大家指教




 


0 0