1.问题或需求描述:
手动创建VS2019 C++工程在某些场景下可能过于繁琐且易出错,例如引用类库可能需要同时配置多个编译模式(debug,realse);可能需要每次手动导入一些基础代码;或许使用一个标准工程副本可以解决问题,但还不够灵活。
2.测试环境:
win10 x64, VS2019 v142
3.解决方法或原理:
3.1方法:
1>将相关库、基础模板等集中打包在一个压缩文件(例:stdlib_tmpl.zip)中。
2>根据使用场景配置相关lua配置文件,然后从lua配置文件快速创建msvc c++工程(自动从模板代码压缩文件'stdlib_tmpl.zip'中抽取所需代码)
3.2方案:
下载链接: https://[百度网盘]/s/1V_5ng4g64OwA5yVX7c_LfA?pwd=cpp0 提取码:cpp0
1>gen_vcx_proj.exe 用法示例:
生成console工程lua配置模板:gen_vcj_proj -mc -f console-cfg.lua
生成dll工程lua配置模板:gen_vcj_proj -md -f dll-cfg.lua
构建console工程:gen_vcj_proj -c -f console-cfg.lua
构建dll工程:gen_vcj_proj -d -f dll-cfg.lua
2>示例 console-cfg.lua:
pro_name = "MyApplication"
root_namespace = "MyApplication"
platform_ver="v142"
project_ver="16.0"
sdk_ver="10.0"
configuration_type = "Application"
charset="Unicode"
head_files = {"framework.h", "utils.h", "udf.h"}
source_files = {"main.cpp", "utils.cpp"}
zip.extract_dir("./stdlib_tmpl.zip", "libs", "./" .. pro_name .. "/libs")
zip.extract_file("./stdlib_tmpl.zip", "console/framework.h", "./" .. pro_name .. "/framework.h")
zip.extract_file("./stdlib_tmpl.zip", "console/udf.h", "./" .. pro_name .. "/udf.h")
zip.extract_file("./stdlib_tmpl.zip", "console/utils.h", "./" .. pro_name .. "/utils.h")
zip.extract_file("./stdlib_tmpl.zip", "console/utils.cpp", "./" .. pro_name .. "/utils.cpp")
zip.extract_file("./stdlib_tmpl.zip", "console/main/cmd_program_option.cpp", "./" .. pro_name .. "/main.cpp")
zip.extract_file("./stdlib_tmpl.zip", ".gitattributes", "./" .. pro_name .. "/.gitattributes")
zip.extract_file("./stdlib_tmpl.zip", ".gitignore", "./" .. pro_name .. "/.gitignore")
function contains(array, element)
for _, value in ipairs(array) do
if value == element then
return true
end
end
return false
end
function array_union(array1, array2)
local result = {}
for _, v in ipairs(array1) do
if not contains(result, v) then
table.insert(result, v)
end
end
for _, v in ipairs(array2) do
if not contains(result, v) then
table.insert(result, v)
end
end
return result
end
function gen_exports_macro(input_str)
local result = ""
for i = 1, #input_str do
local char = input_str:sub(i, i)
if char:match("[%a%d]") then
result = result .. char:upper()
end
end
return result
end
local LibraryConfig = {
is_use = false,
compile = '',
inner_dir = '',
outer_dir = '',
inc_dirs = {},
inc_cpps = {},
lib_dirs = {},
depends = {},
pre_def = {}
}
function LibraryConfig:new(is_use, compile, inner_dir, outer_dir, inc_dirs, inc_cpps, lib_dirs, depends, pre_def)
local o = {}
setmetatable(o, self)
self.__index = self
o.is_use = is_use or self.is_use
o.compile = compile or self.compile
o.inner_dir = inner_dir or self.inner_dir
o.outer_dir = outer_dir or self.outer_dir
o.inc_dirs = inc_dirs or self.inc_dirs
o.inc_cpps = inc_cpps or self.inc_cpps
o.lib_dirs = lib_dirs or self.lib_dirs
o.depends = depends or self.depends
o.pre_def = pre_def or self.pre_def
return o
end
function LibraryConfig:to_string()
local str = ''
str = str .. 'is_use: ' .. tostring(self.is_use) .. '\n'
str = str .. 'compile: ' .. tostring(self.compile) .. '\n'
str = str .. 'inner_dir: ' .. tostring(self.inner_dir) .. '\n'
str = str .. 'outer_dir: ' .. tostring(self.outer_dir) .. '\n'
str = str .. 'inc_dirs: ' .. table.concat(self.inc_dirs, '') .. '\n'
str = str .. 'inc_cpps: ' .. table.concat(self.inc_cpps, '') .. '\n'
str = str .. 'lib_dirs: ' .. table.concat(self.lib_dirs, '') .. '\n'
str = str .. 'depends: ' .. table.concat(self.depends, ';') .. '\n'
str = str .. 'pre_def: ' .. table.concat(self.pre_def, ';')
return str
end
boost_cfg = LibraryConfig:new(
true, '', nil, nil,
{'$(BOOST_ROOT)'},
{},
{'$(BOOST_LIB)'},
{},
{'USE_BOOST'}
)
easylogging_cfg = LibraryConfig:new(
true, '', nil, nil,
{'./libs/easylogging++'},
{'./libs/easylogging++/easylogging++.cc'},
{},
{},
{'ELPP_THREAD_SAFE', 'USE_EASYLOGGINGPP'}
)
loguru_cfg = LibraryConfig:new(
true, '', nil, nil,
{'./libs/loguru'},
{'./libs/loguru/loguru.cpp'},
{},
{},
{'USE_LOGURU'}
)
getopt_cfg = LibraryConfig:new(
false, '', nil, nil,
{'./libs/getopt'},
{},
{},
{},
{'USE_GETOPT'}
)
opencv2_d_cfg = LibraryConfig:new(
true, 'debug', nil, nil,
{'$(opencv2_include)'},
{},
{'$(opencv2_lib)'},
{'$(opencv2_lib_world_d)'},
{'USE_OPENCV2'}
)
opencv2_r_cfg = LibraryConfig:new(
true, 'release', nil, nil,
{'$(opencv2_include)'},
{},
{'$(opencv2_lib)'},
{'$(opencv2_lib_world)'},
{'USE_OPENCV2'}
)
halcon_cfg = LibraryConfig:new(
true, '', nil, nil,
{'$(HALCONROOT)/include', '$(HALCONROOT)/include/halconcpp'},
{},
{'$(HALCONROOT)/lib/$(HALCONARCH)'},
{'halconcpp.lib'},
{'USE_HALCON'}
)
json_cfg = LibraryConfig:new(
true, '', nil, nil,
{'./libs/json-3.11.2'},
{},
{},
{},
{'USE_JSON'}
)
sqlite_cfg = LibraryConfig:new(
false, '', nil, nil,
{'./libs/sqlite-3420000'},
{},
{},
{},
{'USE_SQLITE'}
)
libiconv_cfg = LibraryConfig:new(
true, '', nil, nil,
{'./libs/libiconv-1.17/include'},
{},
{'./libs/libiconv-1.17/lib'},
{'libiconv_a.lib'},
{'USE_LIBICONV'}
)
lua_cfg = LibraryConfig:new(
true, '', nil, nil,
{'./libs/lua-5.4.6/include'},
{},
{'./libs/lua-5.4.6/x64/vc16/lib'},
{'lua5.4.6.lib'},
{'USE_LUA'}
)
thread_pool_cfg = LibraryConfig:new(
false, '', nil, nil,
{'./libs/ThreadPool'},
{},
{},
{},
{'USE_THREADPOOL'}
)
tinyxml2_cfg = LibraryConfig:new(
false, '', nil, nil,
{'./libs/tinyxml2'},
{'./libs/tinyxml2/tinyxml2.cpp'},
{},
{},
{'USE_TINYXML2'}
)
libs = {}
table.insert (libs, boost_cfg)
table.insert (libs, easylogging_cfg)
table.insert (libs, loguru_cfg)
table.insert (libs, getopt_cfg)
table.insert (libs, opencv2_d_cfg)
table.insert (libs, opencv2_r_cfg)
table.insert (libs, halcon_cfg)
table.insert (libs, json_cfg)
table.insert (libs, sqlite_cfg)
table.insert (libs, libiconv_cfg)
table.insert (libs, lua_cfg)
table.insert (libs, thread_pool_cfg)
table.insert (libs, tinyxml2)
-- debug
--~ for i, v in ipairs(libs) do
--~ print(i,':')
--~ print(v:to_string())
--~ end
for _, v in ipairs(libs) do
if v.is_use then
source_files = array_union(source_files, v.inc_cpps)
end
end
local Itemdefinition = {
compile = "Debug|x64",
inc_dirs = {},
lib_dirs = {},
depends = {"%(AdditionalDependencies)"},
pre_def = {"WIN32", "_DEBUG", "_CONSOLE", "ELPP_THREAD_SAFE", "%(PreprocessorDefinitions)"},
sub_system = "Console",
warning_level = "Level3"
}
function Itemdefinition:new(compile, inc_dirs, lib_dirs, depends, pre_def, sub_system, warning_level)
local o = {}
setmetatable(o, self)
self.__index = self
o.compile = compile or self.compile
o.inc_dirs = inc_dirs or self.inc_dirs
o.lib_dirs = lib_dirs or self.lib_dirs
o.depends = depends or self.depends
o.pre_def = pre_def or self.pre_def
o.sub_system = sub_system or self.sub_system
o.warning_level = warning_level or self.warning_level
return o
end
Debug_Win32 = Itemdefinition:new("Debug|Win32",
{},
{},
{"%(AdditionalDependencies)"},
{"WIN32", "_DEBUG", "_CONSOLE", "%(PreprocessorDefinitions)"}
)
Release_Win32 = Itemdefinition:new("Release|Win32",
{},
{},
{"%(AdditionalDependencies)"},
{"WIN32", "NDEBUG", "_CONSOLE", "%(PreprocessorDefinitions)"}
)
Debug_x64 = Itemdefinition:new("Debug|x64",
{},
{},
{"%(AdditionalDependencies)"},
{"_DEBUG", "_CONSOLE", "%(PreprocessorDefinitions)"}
)
Release_x64 = Itemdefinition:new("Release|x64",
{},
{},
{"%(AdditionalDependencies)"},
{"NDEBUG", "_CONSOLE", "%(PreprocessorDefinitions)"}
)
compile_configs = { Debug_Win32, Release_Win32, Debug_x64, Release_x64}
for i, v in ipairs(compile_configs) do
inc_dirs = {}
lib_dirs = {}
depends = {}
pre_def = {}
for i2, v2 in ipairs(libs) do
if v2.is_use then
if v2.compile ~= nil and string.len(v2.compile) > 0 then
if string.find(string.lower(v.compile), string.lower(v2.compile)) ~= nil then
inc_dirs = array_union(inc_dirs, v2.inc_dirs)
lib_dirs = array_union(lib_dirs, v2.lib_dirs)
depends = array_union(depends, v2.depends)
pre_def = array_union(pre_def, v2.pre_def)
end
elseif v2.compile == nil or string.len(v2.compile) == 0 then
inc_dirs = array_union(inc_dirs, v2.inc_dirs)
lib_dirs = array_union(lib_dirs, v2.lib_dirs)
depends = array_union(depends, v2.depends)
pre_def = array_union(pre_def, v2.pre_def)
end
end
end
v.inc_dirs = array_union(inc_dirs, v.inc_dirs)
v.lib_dirs = array_union(lib_dirs, v.lib_dirs)
v.depends = array_union(depends, v.depends)
v.pre_def = array_union(pre_def, v.pre_def)
end
--debug
--~ for _, config in ipairs(compile_configs) do
--~ print("compile: " .. config.compile)
--~ print("inc_dirs: " .. table.concat(config.inc_dirs, ";"))
--~ print("lib_dirs: " .. table.concat(config.lib_dirs, ";"))
--~ print("depends: " .. table.concat(config.depends, ";"))
--~ print("pre_def: " .. table.concat(config.pre_def, ";"))
--~ print("sub_system: " .. config.sub_system)
--~ print("warning_level: " .. config.warning_level)
--~ print("------")
--~ end
- 1.
- 2.
- 3.
- 4.
- 5.
- 6.
- 7.
- 8.
- 9.
- 10.
- 11.
- 12.
- 13.
- 14.
- 15.
- 16.
- 17.
- 18.
- 19.
- 20.
- 21.
- 22.
- 23.
- 24.
- 25.
- 26.
- 27.
- 28.
- 29.
- 30.
- 31.
- 32.
- 33.
- 34.
- 35.
- 36.
- 37.
- 38.
- 39.
- 40.
- 41.
- 42.
- 43.
- 44.
- 45.
- 46.
- 47.
- 48.
- 49.
- 50.
- 51.
- 52.
- 53.
- 54.
- 55.
- 56.
- 57.
- 58.
- 59.
- 60.
- 61.
- 62.
- 63.
- 64.
- 65.
- 66.
- 67.
- 68.
- 69.
- 70.
- 71.
- 72.
- 73.
- 74.
- 75.
- 76.
- 77.
- 78.
- 79.
- 80.
- 81.
- 82.
- 83.
- 84.
- 85.
- 86.
- 87.
- 88.
- 89.
- 90.
- 91.
- 92.
- 93.
- 94.
- 95.
- 96.
- 97.
- 98.
- 99.
- 100.
- 101.
- 102.
- 103.
- 104.
- 105.
- 106.
- 107.
- 108.
- 109.
- 110.
- 111.
- 112.
- 113.
- 114.
- 115.
- 116.
- 117.
- 118.
- 119.
- 120.
- 121.
- 122.
- 123.
- 124.
- 125.
- 126.
- 127.
- 128.
- 129.
- 130.
- 131.
- 132.
- 133.
- 134.
- 135.
- 136.
- 137.
- 138.
- 139.
- 140.
- 141.
- 142.
- 143.
- 144.
- 145.
- 146.
- 147.
- 148.
- 149.
- 150.
- 151.
- 152.
- 153.
- 154.
- 155.
- 156.
- 157.
- 158.
- 159.
- 160.
- 161.
- 162.
- 163.
- 164.
- 165.
- 166.
- 167.
- 168.
- 169.
- 170.
- 171.
- 172.
- 173.
- 174.
- 175.
- 176.
- 177.
- 178.
- 179.
- 180.
- 181.
- 182.
- 183.
- 184.
- 185.
- 186.
- 187.
- 188.
- 189.
- 190.
- 191.
- 192.
- 193.
- 194.
- 195.
- 196.
- 197.
- 198.
- 199.
- 200.
- 201.
- 202.
- 203.
- 204.
- 205.
- 206.
- 207.
- 208.
- 209.
- 210.
- 211.
- 212.
- 213.
- 214.
- 215.
- 216.
- 217.
- 218.
- 219.
- 220.
- 221.
- 222.
- 223.
- 224.
- 225.
- 226.
- 227.
- 228.
- 229.
- 230.
- 231.
- 232.
- 233.
- 234.
- 235.
- 236.
- 237.
- 238.
- 239.
- 240.
- 241.
- 242.
- 243.
- 244.
- 245.
- 246.
- 247.
- 248.
- 249.
- 250.
- 251.
- 252.
- 253.
- 254.
- 255.
- 256.
- 257.
- 258.
- 259.
- 260.
- 261.
- 262.
- 263.
- 264.
- 265.
- 266.
- 267.
- 268.
- 269.
- 270.
- 271.
- 272.
- 273.
- 274.
- 275.
- 276.
- 277.
- 278.
- 279.
- 280.
- 281.
- 282.
- 283.
- 284.
- 285.
- 286.
- 287.
- 288.
- 289.
- 290.
- 291.
- 292.
- 293.
- 294.
- 295.
- 296.
- 297.
- 298.
- 299.
- 300.
- 301.
- 302.
- 303.
- 304.
- 305.
- 306.
- 307.
- 308.
- 309.
- 310.
- 311.
- 312.
- 313.
- 314.
- 315.
- 316.
- 317.
- 318.
- 319.
- 320.
- 321.
- 322.
- 323.
- 324.
- 325.
- 326.
- 327.
- 328.
- 329.
- 330.
- 331.
- 332.
- 333.
- 334.
3>关于lua配置文件:
3.1>lua配置文件需要配置的字段:
3.2>lua zip api:
3.3> LibraryConfig 结构
local LibraryConfig = {
is_use = false, --是否启用库
compile = '', --编译模式,debug,release,nil(nil或空字符串匹配所有模式)
inner_dir = '', --库位于zip中的路径(需要在脚本中自行实现)
outer_dir = '', --需要抽取到的外部目标路径(需要在脚本中自行实现)
inc_dirs = {}, --附加头文件包含目录
inc_cpps = {}, --包含源代码(*.cpp)(适用某些库需包含源代码)
lib_dirs = {}, --库文件目录
depends = {}, --库文件
pre_def = {} --定义预处理符号
}
- 1.
- 2.
- 3.
- 4.
- 5.
- 6.
- 7.
- 8.
- 9.
- 10.
- 11.
3.4> Itemdefinition 结构