diff --git a/cmake_project.lua b/cmake_project.lua index 0bf1510..8a34e0a 100755 --- a/cmake_project.lua +++ b/cmake_project.lua @@ -9,7 +9,7 @@ -- Joel Linn -- UndefinedVertex -- Created: 2013/05/06 --- Copyright: (c) 2008-2020 Jason Perkins and the Premake project +-- Copyright: (c) 2008-2022 Jason Perkins and the Premake project -- local p = premake @@ -35,7 +35,7 @@ function m.files(prj) local tr = project.getsourcetree(prj) tree.traverse(tr, { onleaf = function(node, depth) - + _p(depth, '"%s"', path.getrelative(prj.workspace.location, node.abspath)) -- add generated files @@ -110,118 +110,130 @@ function m.generate(prj) -- output dir _p(1,'set_target_properties("%s" PROPERTIES', prj.name) _p(2, 'OUTPUT_NAME "%s"', cfg.buildtarget.basename) - _p(2, 'ARCHIVE_OUTPUT_DIRECTORY "%s"', path.getrelative(prj.workspace.location, cfg.buildtarget.directory)) - _p(2, 'LIBRARY_OUTPUT_DIRECTORY "%s"', path.getrelative(prj.workspace.location, cfg.buildtarget.directory)) - _p(2, 'RUNTIME_OUTPUT_DIRECTORY "%s"', path.getrelative(prj.workspace.location, cfg.buildtarget.directory)) + local relBinDir = path.getrelative(prj.workspace.location, cfg.buildtarget.directory) + _p(2, 'ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_SOURCE_DIR}/%s"', relBinDir) + _p(2, 'LIBRARY_OUTPUT_DIRECTORY "${CMAKE_SOURCE_DIR}/%s"', relBinDir) + _p(2, 'RUNTIME_OUTPUT_DIRECTORY "${CMAKE_SOURCE_DIR}/%s"', relBinDir) _p(1,')') - _p('endif()') -- include dirs if #cfg.sysincludedirs > 0 then - _p('target_include_directories("%s" SYSTEM PRIVATE', prj.name) + _p(1, 'target_include_directories("%s" SYSTEM PRIVATE', prj.name) for _, includedir in ipairs(cfg.sysincludedirs) do - _x(1, '$<$:%s>', cmake.cfgname(cfg), includedir) + _x(2, '%s', includedir) end - _p(')') + _p(1, ')') end if #cfg.includedirs > 0 then - _p('target_include_directories("%s" PRIVATE', prj.name) + _p(1, 'target_include_directories("%s" PRIVATE', prj.name) for _, includedir in ipairs(cfg.includedirs) do - _x(1, '$<$:%s>', cmake.cfgname(cfg), includedir) + _x(2, '%s', includedir) end - _p(')') + _p(1, ')') end if #cfg.forceincludes > 0 then - _p('if (MSVC)') - _p(1, 'target_compile_options("%s" PRIVATE %s)', prj.name, table.implode(p.tools.msc.getforceincludes(cfg), "", "", " ")) - _p('else()') - _p(1, 'target_compile_options("%s" PRIVATE %s)', prj.name, table.implode(p.tools.gcc.getforceincludes(cfg), "", "", " ")) - _p('endif()') + _p(1, 'if (MSVC)') + _p(2, 'target_compile_options("%s" PRIVATE %s)', prj.name, table.implode(p.tools.msc.getforceincludes(cfg), "", "", " ")) + _p(1, 'else()') + _p(2, 'target_compile_options("%s" PRIVATE %s)', prj.name, table.implode(p.tools.gcc.getforceincludes(cfg), "", "", " ")) + _p(1, 'endif()') end -- defines if #cfg.defines > 0 then - _p('target_compile_definitions("%s" PRIVATE', prj.name) + _p(1, 'target_compile_definitions("%s" PRIVATE', prj.name) for _, define in ipairs(cfg.defines) do - _p(1, '$<$:%s>', cmake.cfgname(cfg), p.esc(define):gsub(' ', '\\ ')) + _p(2, '%s', p.esc(define):gsub(' ', '\\ ')) end - _p(')') + _p(1, ')') end -- lib dirs if #cfg.libdirs > 0 then - _p('target_link_directories("%s" PRIVATE', prj.name) + _p(1, 'target_link_directories("%s" PRIVATE', prj.name) for _, libdir in ipairs(cfg.libdirs) do - _p(1, '$<$:%s>', cmake.cfgname(cfg), libdir) + _p(2, '%s', libdir) end - _p(')') + _p(1, ')') end -- libs local uselinkgroups = isclangorgcc and cfg.linkgroups == p.ON if uselinkgroups or # config.getlinks(cfg, "dependencies", "object") > 0 or #config.getlinks(cfg, "system", "fullpath") > 0 then - _p('target_link_libraries("%s"', prj.name) + _p(1, 'target_link_libraries("%s"', prj.name) -- Do not use toolset here as cmake needs to resolve dependency chains if uselinkgroups then - _p(1, '-Wl,--start-group') + _p(2, '-Wl,--start-group') end for a, link in ipairs(config.getlinks(cfg, "dependencies", "object")) do - _p(1, '$<$:%s>', cmake.cfgname(cfg), link.project.name) + _p(2, '%s', link.project.name) end if uselinkgroups then -- System libraries don't depend on the project - _p(1, '-Wl,--end-group') - _p(1, '-Wl,--start-group') + _p(2, '-Wl,--end-group') + _p(2, '-Wl,--start-group') end for _, link in ipairs(config.getlinks(cfg, "system", "fullpath")) do - _p(1, '$<$:%s>', cmake.cfgname(cfg), link) + _p(2, '%s', link) end if uselinkgroups then - _p(1, '-Wl,--end-group') + _p(2, '-Wl,--end-group') end - _p(')') + _p(1, ')') end -- setting build options - all_build_options = "" - for _, option in ipairs(cfg.buildoptions) do - all_build_options = all_build_options .. option .. " " - end - - if all_build_options ~= "" then - _p('if(CMAKE_BUILD_TYPE STREQUAL %s)', cmake.cfgname(cfg)) - _p(1, 'set_target_properties("%s" PROPERTIES COMPILE_FLAGS %s)', prj.name, all_build_options) - _p('endif()') + if #cfg.buildoptions > 0 then + _p(1, 'set(_TARGET_COMPILE_FLAGS %s)', table.concat(cfg.buildoptions, ' ')) + _p(1, 'string(REPLACE ";" " " _TARGET_COMPILE_FLAGS "${_TARGET_COMPILE_FLAGS}")') + _p(1, 'set_property(TARGET "%s" PROPERTY COMPILE_FLAGS ${_TARGET_COMPILE_FLAGS})', prj.name) + _p(1, 'unset(_TARGET_COMPILE_FLAGS)') end -- setting link options - all_link_options = "" - for _, option in ipairs(cfg.linkoptions) do - all_link_options = all_link_options .. option .. " " + if #cfg.linkoptions > 0 then + _p(1, 'set(_TARGET_LINK_FLAGS %s)', table.concat(cfg.linkoptions, ' ')) + _p(1, 'string(REPLACE ";" " " _TARGET_LINK_FLAGS "${_TARGET_COMPILE_FLAGS}")') + _p(1, 'set_property(TARGET "%s" PROPERTY LINK_FLAGS ${_TARGET_LINK_FLAGS})', prj.name) + _p(1, 'unset(_TARGET_LINK_FLAGS)') end - if all_link_options ~= "" then - _p('if(CMAKE_BUILD_TYPE STREQUAL %s)', cmake.cfgname(cfg)) - _p(1, 'set_target_properties("%s" PROPERTIES LINK_FLAGS "%s")', prj.name, all_link_options) - _p('endif()') - end - if #toolset.getcflags(cfg) > 0 or #toolset.getcxxflags(cfg) > 0 then - _p('target_compile_options("%s" PRIVATE', prj.name) + _p(1, 'target_compile_options("%s" PRIVATE', prj.name) for _, flag in ipairs(toolset.getcflags(cfg)) do - _p(1, '$<$,$>:%s>', cmake.cfgname(cfg), flag) + _p(2, '$<$:%s>', flag) end for _, flag in ipairs(toolset.getcxxflags(cfg)) do - _p(1, '$<$,$>:%s>', cmake.cfgname(cfg), flag) + _p(2, '$<$:%s>', flag) end - _p(')') + _p(1, ')') end + -- setting per fille build options + table.foreachi(prj._.files, function(node) + local fcfg = p.fileconfig.getconfig(node, cfg) + if fcfg then + toolset_flags = {} + if path.iscfile(fcfg.name) then + toolset_flags = toolset.getcflags(fcfg) + else + toolset_flags = toolset.getcxxflags(fcfg) + end + file_build_options = table.concat(table.join(toolset_flags, fcfg.buildoptions), " ") + if file_build_options ~= "" then + _p(1, + 'set_source_files_properties("%s" PROPERTIES COMPILE_FLAGS "%s")', + path.getrelative(prj.workspace.location, fcfg.abspath), + file_build_options) + end + end + end) + -- C++ standard - -- only need to configure it specified + -- only need to configure if specified if (cfg.cppdialect ~= nil and cfg.cppdialect ~= '') or cfg.cppdialect == 'Default' then local standard = {} standard["C++98"] = 98 @@ -239,7 +251,6 @@ function m.generate(prj) local pic = iif(cfg.pic == 'On', 'True', 'False') local lto = iif(cfg.flags.LinkTimeOptimization, 'True', 'False') - _p('if(CMAKE_BUILD_TYPE STREQUAL %s)', cmake.cfgname(cfg)) _p(1, 'set_target_properties("%s" PROPERTIES', prj.name) _p(2, 'CXX_STANDARD %s', standard[cfg.cppdialect]) _p(2, 'CXX_STANDARD_REQUIRED YES') @@ -247,7 +258,6 @@ function m.generate(prj) _p(2, 'POSITION_INDEPENDENT_CODE %s', pic) _p(2, 'INTERPROCEDURAL_OPTIMIZATION %s', lto) _p(1, ')') - _p('endif()') end -- precompiled headers @@ -277,39 +287,37 @@ function m.generate(prj) pch = project.getrelative(cfg.project, path.getabsolute(pch)) end - _p('if(CMAKE_BUILD_TYPE STREQUAL %s)', cmake.cfgname(cfg)) - _p('target_precompile_headers("%s" PUBLIC %s)', prj.name, pch) - _p('endif()') + _p(1, 'target_precompile_headers("%s" PUBLIC %s)', prj.name, pch) end -- pre/post buildcommands if cfg.prebuildmessage or #cfg.prebuildcommands > 0 then -- add_custom_command PRE_BUILD runs just before generating the target -- so instead, use add_custom_target to run it before any rule (as obj) - _p('add_custom_target(prebuild-%s', prj.name) + _p(1, 'add_custom_target(prebuild-%s', prj.name) if cfg.prebuildmessage then local command = os.translateCommandsAndPaths("{ECHO} " .. cfg.prebuildmessage, cfg.project.basedir, cfg.project.location) - _p(' COMMAND %s', command) + _p(2, 'COMMAND %s', command) end local commands = os.translateCommandsAndPaths(cfg.prebuildcommands, cfg.project.basedir, cfg.project.location) for _, command in ipairs(commands) do - _p(' COMMAND %s', command) + _p(2, 'COMMAND %s', command) end - _p(')') - _p('add_dependencies(%s prebuild-%s)', prj.name, prj.name) + _p(1, ')') + _p(1, 'add_dependencies(%s prebuild-%s)', prj.name, prj.name) end if cfg.postbuildmessage or #cfg.postbuildcommands > 0 then - _p('add_custom_command(TARGET %s POST_BUILD', prj.name) + _p(1, 'add_custom_command(TARGET %s POST_BUILD', prj.name) if cfg.postbuildmessage then local command = os.translateCommandsAndPaths("{ECHO} " .. cfg.postbuildmessage, cfg.project.basedir, cfg.project.location) - _p(' COMMAND %s', command) + _p(2, 'COMMAND %s', command) end local commands = os.translateCommandsAndPaths(cfg.postbuildcommands, cfg.project.basedir, cfg.project.location) for _, command in ipairs(commands) do - _p(' COMMAND %s', command) + _p(2, 'COMMAND %s', command) end - _p(')') + _p(1, ')') end -- custom command @@ -317,20 +325,20 @@ function m.generate(prj) if #fileconfig.buildcommands == 0 or #fileconfig.buildoutputs == 0 then return end - _p('add_custom_command(TARGET OUTPUT %s', table.implode(project.getrelative(cfg.project, fileconfig.buildoutputs),"",""," ")) + _p(1, 'add_custom_command(TARGET OUTPUT %s', table.implode(project.getrelative(cfg.project, fileconfig.buildoutputs),"",""," ")) if fileconfig.buildmessage then - _p(' COMMAND %s', os.translateCommandsAndPaths('{ECHO} ' .. fileconfig.buildmessage, cfg.project.basedir, cfg.project.location)) + _p(2, 'COMMAND %s', os.translateCommandsAndPaths('{ECHO} ' .. fileconfig.buildmessage, cfg.project.basedir, cfg.project.location)) end for _, command in ipairs(fileconfig.buildcommands) do - _p(' COMMAND %s', os.translateCommandsAndPaths(command, cfg.project.basedir, cfg.project.location)) + _p(2, 'COMMAND %s', os.translateCommandsAndPaths(command, cfg.project.basedir, cfg.project.location)) end if filename ~= "" and #fileconfig.buildinputs ~= 0 then filename = filename .. " " end if filename ~= "" or #fileconfig.buildinputs ~= 0 then - _p(' DEPENDS %s', filename .. table.implode(fileconfig.buildinputs,"",""," ")) + _p(2, 'DEPENDS %s', filename .. table.implode(fileconfig.buildinputs,"",""," ")) end - _p(')') + _p(1, ')') end local tr = project.getsourcetree(cfg.project) p.tree.traverse(tr, { @@ -353,6 +361,7 @@ function m.generate(prj) end }) addCustomCommand(cfg, "") + _p('endif()') end -- restore path.getDefaultSeparator = oldGetDefaultSeparator diff --git a/cmake_workspace.lua b/cmake_workspace.lua index 3f65121..b1640f9 100644 --- a/cmake_workspace.lua +++ b/cmake_workspace.lua @@ -77,8 +77,8 @@ function m.generate(wks) -- Clear default flags p.w('set(CMAKE_MSVC_RUNTIME_LIBRARY "")') - p.w('set(CMAKE_C_FLAGS "")') - p.w('set(CMAKE_CXX_FLAGS "")') + p.w('set(CMAKE_C_FLAGS "$ENV{CFLAGS}")') + p.w('set(CMAKE_CXX_FLAGS "$ENV{CXXFLAGS}")') for _, cfg in pairs(cfgs) do p.w('set(CMAKE_C_FLAGS_%s "")', string.upper(cfg)) p.w('set(CMAKE_CXX_FLAGS_%s "")', string.upper(cfg))