工作需要libzimg库,下载源代码下面有一个"_msvc"的子目录,都已经做好适配了。但问题是,这个适配是适配当前的Visual studio C++的版本的,而一些低一级的版本就老报错。要解决这个问题,其实也简单,这个需要CMake(CMake原理)。而libzimg提供的是经典一套的autoconf工具链。所以我没有功夫去研究CMake了,还是直接用的nmake解决问题。
命令行都是相通的。
工作场景:libzimg最新版本
VC2015 Express,Windows 7 SDK
首先构筑环境设置
一般在VS安装以后,会存在一个环境变量:VSnnnCOMMTOOLS(nnn版本号,VS2015就是240),用 set vs命令可以查看具体版本号:
C:\Qt\zimg-2.8>set vs
VS140COMNTOOLS=C:\Program Files (x86)\Microsoft Visual Studio 14.0\Common7\Tools\
VSSDK140Install=C:\Program Files (x86)\Microsoft Visual Studio 14.0\VSSDK\
C:\Qt\zimg-2.8>dir "%VS140COMNTOOLS%\..\..\VC\vcvarsall.bat"
驱动器 C 中的卷是 Windows 7 SSD
卷的序列号是 44D7-DBAA
C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC 的目录
2016/06/09 22:25 3,337 vcvarsall.bat
1 个文件 3,337 字节
0 个目录 3,597,721,600 可用字节
C:\Qt\zimg-2.8>
里面有一个 vcvarsall.bat 文件。编译哪个平台,就设置里面的参数。默认x86是32位的,如果要64就是 call vcvarsall.bat x64,具体去看面的源代码。如果没有,会出现LIBCMT.lib没有找到的问题
Microsoft (R) Incremental Linker Version 14.00.24215.1
Copyright (C) Microsoft Corporation. All rights reserved.
LINK : fatal error LNK1104: 无法打开文件“LIBCMT.lib”
NMAKE : fatal error U1077: “"C:\Program Files (x86)\Microsoft Visual Studio 14.
0\Common7\Tools\\..\..\vc\bin\link.EXE"”: 返回代码“0x450”
另外需要添加 PATH : PATH=%PATH%;%VS140COMNTOOLS%\..\..\vc\bin
VS2017环境设置看这里:https://blog.youkuaiyun.com/harborian/article/details/126297812
nmake的一些点滴:
https://learn.microsoft.com/zh-cn/cpp/build/reference/special-nmake-macros
nmake和make有一些不兼容的地方:
- make的子目录递归 make -C subdir 可以搜索subdir下的Makefile,而nmake的-C参数不是这个意义,需要自己的文件里 CD subsir,nmake -F makefile 进行处理。
- make文件内搜索子目录路径。make用 VPATH,nmake使用{src1:src2:}。
- 搜索子目录可以带入规则
libzimg的目录结构非常合理,但嵌套麻烦,查了下没有相同的文件名,那么就写一个Makefile就凑合了。
cat /mnt/Qt/zimg-2.8/_msvc/zimg/zimg.vcxproj |\
grep Include | cut -d'"' -f2 | \
awk -F"\\" '{print $NF}' | sort | uniq -c | more
nmake点滴:
- NMAKE [选项] [/f makefile] [/x stderrfile] [macrodefs] [targets]
其中 macrodefs是宏定义;targets是里面的目标(块规则名),默认第一个伪目标 - nmake /P 查看nmake内部的预定义变量和配置,了解默认参数。
- nmake /A 查看nmake的实际解析的makefile文件的操作步骤。调试很有用。
- $*$**的解释要看 https://learn.microsoft.com/zh-cn/cpp/build/reference/special-nmake-macros 。
- 点规则的定义,https://learn.microsoft.com/zh-cn/cpp/build/reference/inference-rules,如果文件名是cpp的话,那么点规则要看补充默认点规则。可能原来的是 .cc.obj,而新的是.cpp.obj
- make文件需要 -L[连接路径名] -l(小写l,库名还不要lib的名称开头或结尾的一些特别明明规则),而nmake需要用 /libpath:,库名直接和obj一样写在参数内。如果是dl的,dll的lib可以用 /DYNAMICBASE "dll.lib"来处理也行,都可以。具体看手册。
移植过程没有太大困难,就是vs2015不支持C++18的新特性constexpr,所以相关的static_map开头需要屏蔽掉,constexpr取消了。其他没有什么问题,就是调整目录的事情。zimg 2.4是最后支持MSVC 2015的版本。可以借鉴_MSVC目录的文件,照抄命令行参数。zimg 3.0就需要新版本的C++特性,所以还是用zimg 2.9
#if __cplusplus >= 201402L || (defined(_MSVC_LANG) && _MSVC_LANG >= 201402L)
//#define SM_CONSTEXPR_14 constexpr
#define SM_CONSTEXPR_14
#else
#define SM_CONSTEXPR_14
#endif
由于我只要dll和一个exe就可以了。所以,Makefle只做了两个。保持原来的目录结构。
C:\Qt\zimg-2.9 的目录
2023/03/22 13:10 <DIR> .
2023/03/22 13:10 <DIR> ..
2023/03/22 13:10 141 .coverity-prepare.sh
2023/03/22 13:10 585 .gitignore
2023/03/22 13:10 114 .gitmodules
2023/03/22 13:10 561 .travis-script.sh
2023/03/22 13:10 1,772 .travis.yml
2023/03/22 13:10 50 autogen.sh
2023/03/22 13:10 5,566 ChangeLog
2023/03/22 13:10 4,120 configure.ac
2023/03/22 13:10 484 COPYING
2023/03/22 13:10 <DIR> doc
2023/03/22 13:10 0 dummy.cpp
2023/03/22 13:10 <DIR> m4
2023/03/22 13:10 11,600 Makefile.am
2023/03/22 13:10 3,432 README.md
2023/03/22 13:10 <DIR> src
2023/03/22 13:10 <DIR> test
2023/03/22 13:10 372 zimg.pc.in
2023/03/22 13:10 <DIR> _msvc
13 个文件 28,797 字节
C:\Qt\zimg-2.9\_msvc 的目录
2023/03/22 13:10 <DIR> .
2023/03/22 13:10 <DIR> ..
2023/03/23 12:33 <DIR> dll
2023/03/22 13:10 <DIR> testapp
2023/03/22 13:10 <DIR> testcommon
2023/03/22 13:10 <DIR> unit_test
2023/03/22 13:10 <DIR> zimg
2023/03/22 13:10 381 zimg.def
2023/03/22 13:10 16,542 zimg.sln
2023/03/22 13:10 <DIR> _example_alpha
2023/03/22 13:10 <DIR> _example_api
2023/03/22 13:10 <DIR> _example_api_c
2023/03/23 12:33 <DIR> _example_hdr
2023/03/22 13:10 <DIR> _example_interlace
2023/03/22 13:10 <DIR> _example_tile
_dll里面的Makefile.vs
#
# Makefile for Microsoft Visual Studio
#
CFLAGS=/I..\..\src\zimg
CC=cl /nologo
LINK=link /nologo /subsystem:console
DEFINES=/DWIN32 /D_WIN32_WINNT=0x0400 /DNDEBUG /DLIBDE265_EXPORTS /D_CRT_SECURE_NO_WARNINGS /DHAVE_SSE4_1 /DHAVE_STDINT_H
#CFLAGS=$(CFLAGS) /MT /Ox /Ob2 /Oi /TP /W4 /GL /EHsc
CFLAGS=$(CFLAGS) /GS /GL /W3 /Gy /Zc:wchar_t /Zi /Gm- /O2 /sdl /Zc:inline /fp:precise /D "_UNICODE" /D "UNICODE" /errorReport:prompt /WX- /Zc:forScope /Gd /Oi /MD /EHsc /nologo
# type conversion, possible loss of data
CFLAGS=$(CFLAGS) /wd4244
# unreferenced formal parameter
CFLAGS=$(CFLAGS) /wd4100
# local variable is initialized but not referenced
CFLAGS=$(CFLAGS) /wd4189
# unreferenced local function has been removed
CFLAGS=$(CFLAGS) /wd4505
# padded structures
CFLAGS=$(CFLAGS) /wd4324
# conversion signed/unsigned
CFLAGS=$(CFLAGS) /wd4245
# comparison signed/unsigned
CFLAGS=$(CFLAGS) /wd4018 /wd4389
# possible loss of data with return
CFLAGS=$(CFLAGS) /wd4267
# forcing value to bool (performance warning)
CFLAGS=$(CFLAGS) /wd4800
CFLAGS=$(CFLAGS) $(DEFINES)
OBJS=..\..\src\zimg\api\zimg.obj \
..\..\src\zimg\colorspace\colorspace.obj \
..\..\src\zimg\colorspace\colorspace_param.obj \
..\..\src\zimg\colorspace\gamma.obj \
..\..\src\zimg\colorspace\graph.obj \
..\..\src\zimg\colorspace\matrix3.obj \
..\..\src\zimg\colorspace\operation.obj \
..\..\src\zimg\colorspace\operation_impl.obj \
..\..\src\zimg\colorspace\x86\gamma_constants_avx512.obj \
..\..\src\zimg\colorspace\x86\operation_impl_avx.obj \
..\..\src\zimg\colorspace\x86\operation_impl_avx2.obj \
..\..\src\zimg\colorspace\x86\operation_impl_avx512.obj \
..\..\src\zimg\colorspace\x86\operation_impl_sse.obj \
..\..\src\zimg\colorspace\x86\operation_impl_sse2.obj \
..\..\src\zimg\colorspace\x86\operation_impl_x86.obj \
..\..\src\zimg\common\cpuinfo.obj \
..\..\src\zimg\common\libm_wrapper.obj \
..\..\src\zimg\common\matrix.obj \
..\..\src\zimg\common\x86\cpuinfo_x86.obj \
..\..\src\zimg\common\x86\x86util.obj \
..\..\src\zimg\depth\blue.obj \
..\..\src\zimg\depth\depth.obj \
..\..\src\zimg\depth\depth_convert.obj \
..\..\src\zimg\depth\dither.obj \
..\..\src\zimg\depth\quantize.obj \
..\..\src\zimg\depth\x86\depth_convert_avx2.obj \
..\..\src\zimg\depth\x86\depth_convert_avx512.obj \
..\..\src\zimg\depth\x86\depth_convert_sse2.obj \
..\..\src\zimg\depth\x86\depth_convert_x86.obj \
..\..\src\zimg\depth\x86\dither_avx2.obj \
..\..\src\zimg\depth\x86\dither_avx512.obj \
..\..\src\zimg\depth\x86\dither_sse2.obj \
..\..\src\zimg\depth\x86\dither_x86.obj \
..\..\src\zimg\depth\x86\error_diffusion_avx2.obj \
..\..\src\zimg\depth\x86\error_diffusion_sse2.obj \
..\..\src\zimg\depth\x86\f16c_ivb.obj \
..\..\src\zimg\depth\x86\f16c_sse2.obj \
..\..\src\zimg\graph\copy_filter.obj \
..\..\src\zimg\graph\filtergraph.obj \
..\..\src\zimg\graph\graphbuilder.obj \
..\..\src\zimg\resize\filter.obj \
..\..\src\zimg\resize\resize.obj \
..\..\src\zimg\resize\resize_impl.obj \
..\..\src\zimg\resize\x86\resize_impl_avx.obj \
..\..\src\zimg\resize\x86\resize_impl_avx2.obj \
..\..\src\zimg\resize\x86\resize_impl_avx512.obj \
..\..\src\zimg\resize\x86\resize_impl_sse.obj \
..\..\src\zimg\resize\x86\resize_impl_sse2.obj \
..\..\src\zimg\resize\x86\resize_impl_x86.obj \
..\..\src\zimg\unresize\bilinear.obj \
..\..\src\zimg\unresize\unresize.obj \
..\..\src\zimg\unresize\unresize_impl.obj
all: z.dll
.c.obj:
$(CC) /c $*.c /Fo$*.obj $(CFLAGS)
.cc.obj:
$(CC) /c $*.cc /Fo$*.obj $(CFLAGS)
.cpp.obj:
$(CC) /c $*.cpp /Fo$*.obj $(CFLAGS)
.cxx.obj:
$(CC) /c $*.cxx /Fo$*.obj $(CFLAGS)
z.dll: $(OBJS)
$(LINK) /def:..\zimg.def /dll /out:z.dll $**
clean:
del z.dll z.lib z.exp
del $(OBJS)
_example_hdr里面的Makefile
#
# Makefile for Microsoft Visual Studio
#
CFLAGS=/I..\..\src\zimg\api /I..\..\src/testcommon
CC=cl /nologo
LINK=link /nologo /subsystem:console
DEFINES=/DWIN32 /D_WIN32_WINNT=0x0400 /DNDEBUG /DLIBDE265_EXPORTS /D_CRT_SECURE_NO_WARNINGS /DHAVE_SSE4_1 /DHAVE_STDINT_H
LDFLAGS=/nologo /subsystem:console
LDFLAGS=$(LFLAGS) /IMPLIB:z.lib /DYNAMICBASE "z.lib" /libpath:..\dll
CFLAGS=$(CFLAGS) /MT /Ox /Ob2 /Oi /TP /W4 /GL /EHsc /Gd
# type conversion, possible loss of data
CFLAGS=$(CFLAGS) /wd4244
# unreferenced formal parameter
CFLAGS=$(CFLAGS) /wd4100
# local variable is initialized but not referenced
CFLAGS=$(CFLAGS) /wd4189
# unreferenced local function has been removed
CFLAGS=$(CFLAGS) /wd4505
# padded structures
CFLAGS=$(CFLAGS) /wd4324
# conversion signed/unsigned
CFLAGS=$(CFLAGS) /wd4245
# comparison signed/unsigned
CFLAGS=$(CFLAGS) /wd4018 /wd4389
# possible loss of data with return
CFLAGS=$(CFLAGS) /wd4267
# forcing value to bool (performance warning)
CFLAGS=$(CFLAGS) /wd4800
CFLAGS=$(CFLAGS) $(DEFINES)
OBJS=..\..\src\testcommon\argparse.obj \
..\..\src\testcommon\mmap.obj \
..\..\src\testcommon\win32_bitmap.obj \
..\..\doc\example\hdr_example.obj
OBJSV30=..\..\src\testcommon\argparse.obj \
..\..\src\testcommon\mmap.obj \
..\..\src\testcommon\win32_bitmap.obj \
..\..\doc\example\hdr_example_v30.obj
all: hdr_example.exe
.c.obj:
$(CC) /c $*.c /Fo$*.obj $(CFLAGS)
.cc.obj:
$(CC) /c $*.cc /Fo$*.obj $(CFLAGS)
.cpp.obj:
$(CC) /c $*.cpp /Fo$*.obj $(CFLAGS)
.cxx.obj:
$(CC) /c $*.cxx /Fo$*.obj $(CFLAGS)
hdr_example.exe: $(OBJS)
$(LINK) /out:hdr_example.exe $(LFLAGS) $**
hdr_example_v30.exe: $(OBJSV30)
$(LINK) /out:hdr_example_v30.exe $(LFLAGS) $**
clean:
del hdr_example.exe hdr_example_v30.exe
del $(OBJS)
其实其他的也一样,ffmpeg的移植也能这么抄作业。就是一些关联关系,我移植了好几个库文件,用MSVC编译通过。